1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 2004-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6848b8605Smrg * Copyright © 2010, 2011 Intel Corporation
7848b8605Smrg *
8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
9848b8605Smrg * copy of this software and associated documentation files (the "Software"),
10848b8605Smrg * to deal in the Software without restriction, including without limitation
11848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
13848b8605Smrg * Software is furnished to do so, subject to the following conditions:
14848b8605Smrg *
15848b8605Smrg * The above copyright notice and this permission notice shall be included
16848b8605Smrg * in all copies or substantial portions of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg */
26848b8605Smrg
27848b8605Smrg#include <stdlib.h>
28b8e80941Smrg#include <inttypes.h>  /* for PRIx64 macro */
29b8e80941Smrg#include <math.h>
30848b8605Smrg
31848b8605Smrg#include "main/context.h"
32848b8605Smrg#include "main/shaderapi.h"
33848b8605Smrg#include "main/shaderobj.h"
34b8e80941Smrg#include "main/uniforms.h"
35b8e80941Smrg#include "compiler/glsl/ir.h"
36b8e80941Smrg#include "compiler/glsl/ir_uniform.h"
37b8e80941Smrg#include "compiler/glsl/glsl_parser_extras.h"
38b8e80941Smrg#include "compiler/glsl/program.h"
39b8e80941Smrg#include "util/bitscan.h"
40848b8605Smrg
41848b8605Smrg
42848b8605Smrgextern "C" void GLAPIENTRY
43848b8605Smrg_mesa_GetActiveUniform(GLuint program, GLuint index,
44848b8605Smrg                       GLsizei maxLength, GLsizei *length, GLint *size,
45848b8605Smrg                       GLenum *type, GLcharARB *nameOut)
46848b8605Smrg{
47848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
48b8e80941Smrg   struct gl_shader_program *shProg;
49b8e80941Smrg   struct gl_program_resource *res;
50848b8605Smrg
51b8e80941Smrg   if (maxLength < 0) {
52b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)");
53848b8605Smrg      return;
54b8e80941Smrg   }
55848b8605Smrg
56b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
57b8e80941Smrg   if (!shProg)
58848b8605Smrg      return;
59848b8605Smrg
60b8e80941Smrg   res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
61b8e80941Smrg                                           GL_UNIFORM, index);
62848b8605Smrg
63b8e80941Smrg   if (!res) {
64b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
65b8e80941Smrg      return;
66848b8605Smrg   }
67848b8605Smrg
68b8e80941Smrg   if (nameOut)
69b8e80941Smrg      _mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength,
70b8e80941Smrg                                      length, nameOut, "glGetActiveUniform");
71b8e80941Smrg   if (type)
72b8e80941Smrg      _mesa_program_resource_prop((struct gl_shader_program *) shProg,
73b8e80941Smrg                                  res, index, GL_TYPE, (GLint*) type,
74b8e80941Smrg                                  "glGetActiveUniform");
75b8e80941Smrg   if (size)
76b8e80941Smrg      _mesa_program_resource_prop((struct gl_shader_program *) shProg,
77b8e80941Smrg                                  res, index, GL_ARRAY_SIZE, (GLint*) size,
78b8e80941Smrg                                  "glGetActiveUniform");
79b8e80941Smrg}
80848b8605Smrg
81b8e80941Smrgstatic GLenum
82b8e80941Smrgresource_prop_from_uniform_prop(GLenum uni_prop)
83b8e80941Smrg{
84b8e80941Smrg   switch (uni_prop) {
85b8e80941Smrg   case GL_UNIFORM_TYPE:
86b8e80941Smrg      return GL_TYPE;
87b8e80941Smrg   case GL_UNIFORM_SIZE:
88b8e80941Smrg      return GL_ARRAY_SIZE;
89b8e80941Smrg   case GL_UNIFORM_NAME_LENGTH:
90b8e80941Smrg      return GL_NAME_LENGTH;
91b8e80941Smrg   case GL_UNIFORM_BLOCK_INDEX:
92b8e80941Smrg      return GL_BLOCK_INDEX;
93b8e80941Smrg   case GL_UNIFORM_OFFSET:
94b8e80941Smrg      return GL_OFFSET;
95b8e80941Smrg   case GL_UNIFORM_ARRAY_STRIDE:
96b8e80941Smrg      return GL_ARRAY_STRIDE;
97b8e80941Smrg   case GL_UNIFORM_MATRIX_STRIDE:
98b8e80941Smrg      return GL_MATRIX_STRIDE;
99b8e80941Smrg   case GL_UNIFORM_IS_ROW_MAJOR:
100b8e80941Smrg      return GL_IS_ROW_MAJOR;
101b8e80941Smrg   case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
102b8e80941Smrg      return GL_ATOMIC_COUNTER_BUFFER_INDEX;
103b8e80941Smrg   default:
104b8e80941Smrg      return 0;
105848b8605Smrg   }
106848b8605Smrg}
107848b8605Smrg
108848b8605Smrgextern "C" void GLAPIENTRY
109848b8605Smrg_mesa_GetActiveUniformsiv(GLuint program,
110848b8605Smrg			  GLsizei uniformCount,
111848b8605Smrg			  const GLuint *uniformIndices,
112848b8605Smrg			  GLenum pname,
113848b8605Smrg			  GLint *params)
114848b8605Smrg{
115848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
116848b8605Smrg   struct gl_shader_program *shProg;
117b8e80941Smrg   struct gl_program_resource *res;
118b8e80941Smrg   GLenum res_prop;
119848b8605Smrg
120848b8605Smrg   if (uniformCount < 0) {
121848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
122848b8605Smrg		  "glGetActiveUniformsiv(uniformCount < 0)");
123848b8605Smrg      return;
124848b8605Smrg   }
125848b8605Smrg
126b8e80941Smrg   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
127b8e80941Smrg   if (!shProg)
128b8e80941Smrg      return;
129b8e80941Smrg
130b8e80941Smrg   res_prop = resource_prop_from_uniform_prop(pname);
131848b8605Smrg
132b8e80941Smrg   /* We need to first verify that each entry exists as active uniform. If
133b8e80941Smrg    * not, generate error and do not cause any other side effects.
134b8e80941Smrg    *
135b8e80941Smrg    * In the case of and error condition, Page 16 (section 2.3.1 Errors)
136b8e80941Smrg    * of the OpenGL 4.5 spec says:
137b8e80941Smrg    *
138b8e80941Smrg    *     "If the generating command modifies values through a pointer argu-
139b8e80941Smrg    *     ment, no change is made to these values."
140b8e80941Smrg    */
141b8e80941Smrg   for (int i = 0; i < uniformCount; i++) {
142b8e80941Smrg      if (!_mesa_program_resource_find_index(shProg, GL_UNIFORM,
143b8e80941Smrg                                              uniformIndices[i])) {
144b8e80941Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
145b8e80941Smrg         return;
146848b8605Smrg      }
147848b8605Smrg   }
148848b8605Smrg
149b8e80941Smrg   for (int i = 0; i < uniformCount; i++) {
150b8e80941Smrg      res = _mesa_program_resource_find_index(shProg, GL_UNIFORM,
151b8e80941Smrg                                              uniformIndices[i]);
152b8e80941Smrg      if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i],
153b8e80941Smrg                                       res_prop, &params[i],
154b8e80941Smrg                                       "glGetActiveUniformsiv"))
155848b8605Smrg         break;
156848b8605Smrg   }
157848b8605Smrg}
158848b8605Smrg
159848b8605Smrgstatic struct gl_uniform_storage *
160b8e80941Smrgvalidate_uniform_parameters(GLint location, GLsizei count,
161b8e80941Smrg                            unsigned *array_index,
162b8e80941Smrg                            struct gl_context *ctx,
163b8e80941Smrg                            struct gl_shader_program *shProg,
164b8e80941Smrg                            const char *caller)
165848b8605Smrg{
166b8e80941Smrg   if (shProg == NULL) {
167848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
168848b8605Smrg      return NULL;
169848b8605Smrg   }
170848b8605Smrg
171848b8605Smrg   /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
172848b8605Smrg    *
173848b8605Smrg    *     "If a negative number is provided where an argument of type sizei or
174848b8605Smrg    *     sizeiptr is specified, the error INVALID_VALUE is generated."
175848b8605Smrg    */
176848b8605Smrg   if (count < 0) {
177848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller);
178848b8605Smrg      return NULL;
179848b8605Smrg   }
180848b8605Smrg
181b8e80941Smrg   /* Check that the given location is in bounds of uniform remap table.
182b8e80941Smrg    * Unlinked programs will have NumUniformRemapTable == 0, so we can take
183b8e80941Smrg    * the shProg->data->LinkStatus check out of the main path.
184b8e80941Smrg    */
185b8e80941Smrg   if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) {
186b8e80941Smrg      if (!shProg->data->LinkStatus)
187b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
188b8e80941Smrg                     caller);
189b8e80941Smrg      else
190b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
191b8e80941Smrg                     caller, location);
192b8e80941Smrg
193b8e80941Smrg      return NULL;
194b8e80941Smrg   }
195b8e80941Smrg
196b8e80941Smrg   if (location == -1) {
197b8e80941Smrg      if (!shProg->data->LinkStatus)
198b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
199b8e80941Smrg                     caller);
200b8e80941Smrg
201848b8605Smrg      return NULL;
202848b8605Smrg   }
203848b8605Smrg
204848b8605Smrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
205848b8605Smrg    *
206848b8605Smrg    *     "If any of the following conditions occur, an INVALID_OPERATION
207848b8605Smrg    *     error is generated by the Uniform* commands, and no uniform values
208848b8605Smrg    *     are changed:
209848b8605Smrg    *
210848b8605Smrg    *     ...
211848b8605Smrg    *
212848b8605Smrg    *         - if no variable with a location of location exists in the
213848b8605Smrg    *           program object currently in use and location is not -1,
214848b8605Smrg    *         - if count is greater than one, and the uniform declared in the
215848b8605Smrg    *           shader is not an array variable,
216848b8605Smrg    */
217848b8605Smrg   if (location < -1 || !shProg->UniformRemapTable[location]) {
218848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
219848b8605Smrg                  caller, location);
220848b8605Smrg      return NULL;
221848b8605Smrg   }
222848b8605Smrg
223848b8605Smrg   /* If the driver storage pointer in remap table is -1, we ignore silently.
224848b8605Smrg    *
225848b8605Smrg    * GL_ARB_explicit_uniform_location spec says:
226848b8605Smrg    *     "What happens if Uniform* is called with an explicitly defined
227848b8605Smrg    *     uniform location, but that uniform is deemed inactive by the
228848b8605Smrg    *     linker?
229848b8605Smrg    *
230848b8605Smrg    *     RESOLVED: The call is ignored for inactive uniform variables and
231848b8605Smrg    *     no error is generated."
232848b8605Smrg    *
233848b8605Smrg    */
234848b8605Smrg   if (shProg->UniformRemapTable[location] ==
235848b8605Smrg       INACTIVE_UNIFORM_EXPLICIT_LOCATION)
236848b8605Smrg      return NULL;
237848b8605Smrg
238848b8605Smrg   struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location];
239848b8605Smrg
240b8e80941Smrg   /* Even though no location is assigned to a built-in uniform and this
241b8e80941Smrg    * function should already have returned NULL, this test makes it explicit
242b8e80941Smrg    * that we are not allowing to update the value of a built-in.
243b8e80941Smrg    */
244b8e80941Smrg   if (uni->builtin)
245848b8605Smrg      return NULL;
246848b8605Smrg
247b8e80941Smrg   if (uni->array_elements == 0) {
248b8e80941Smrg      if (count > 1) {
249b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
250b8e80941Smrg                     "%s(count = %u for non-array \"%s\"@%d)",
251b8e80941Smrg                     caller, count, uni->name, location);
252b8e80941Smrg         return NULL;
253b8e80941Smrg      }
254848b8605Smrg
255b8e80941Smrg      assert((location - uni->remap_location) == 0);
256b8e80941Smrg      *array_index = 0;
257b8e80941Smrg   } else {
258b8e80941Smrg      /* The array index specified by the uniform location is just the uniform
259b8e80941Smrg       * location minus the base location of of the uniform.
260b8e80941Smrg       */
261b8e80941Smrg      *array_index = location - uni->remap_location;
262b8e80941Smrg
263b8e80941Smrg      /* If the uniform is an array, check that array_index is in bounds.
264b8e80941Smrg       * array_index is unsigned so no need to check for less than zero.
265b8e80941Smrg       */
266b8e80941Smrg      if (*array_index >= uni->array_elements) {
267b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
268b8e80941Smrg                     caller, location);
269b8e80941Smrg         return NULL;
270b8e80941Smrg      }
271848b8605Smrg   }
272848b8605Smrg   return uni;
273848b8605Smrg}
274848b8605Smrg
275848b8605Smrg/**
276848b8605Smrg * Called via glGetUniform[fiui]v() to get the current value of a uniform.
277848b8605Smrg */
278848b8605Smrgextern "C" void
279848b8605Smrg_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
280848b8605Smrg		  GLsizei bufSize, enum glsl_base_type returnType,
281848b8605Smrg		  GLvoid *paramsOut)
282848b8605Smrg{
283848b8605Smrg   struct gl_shader_program *shProg =
284848b8605Smrg      _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
285848b8605Smrg   unsigned offset;
286848b8605Smrg
287848b8605Smrg   struct gl_uniform_storage *const uni =
288b8e80941Smrg      validate_uniform_parameters(location, 1, &offset,
289b8e80941Smrg                                  ctx, shProg, "glGetUniform");
290b8e80941Smrg   if (uni == NULL) {
291b8e80941Smrg      /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
292b8e80941Smrg       * spec says:
293b8e80941Smrg       *
294b8e80941Smrg       *     "The error INVALID_OPERATION is generated if program has not been
295b8e80941Smrg       *     linked successfully, or if location is not a valid location for
296b8e80941Smrg       *     program."
297b8e80941Smrg       *
298b8e80941Smrg       * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
299b8e80941Smrg       * says:
300b8e80941Smrg       *
301b8e80941Smrg       *     "If the value of location is -1, the Uniform* commands will
302b8e80941Smrg       *     silently ignore the data passed in, and the current uniform
303b8e80941Smrg       *     values will not be changed."
304b8e80941Smrg       *
305b8e80941Smrg       * Allowing -1 for the location parameter of glUniform allows
306b8e80941Smrg       * applications to avoid error paths in the case that, for example, some
307b8e80941Smrg       * uniform variable is removed by the compiler / linker after
308b8e80941Smrg       * optimization.  In this case, the new value of the uniform is dropped
309b8e80941Smrg       * on the floor.  For the case of glGetUniform, there is nothing
310b8e80941Smrg       * sensible to do for a location of -1.
311b8e80941Smrg       *
312b8e80941Smrg       * If the location was -1, validate_unfirom_parameters will return NULL
313b8e80941Smrg       * without raising an error.  Raise the error here.
314b8e80941Smrg       */
315b8e80941Smrg      if (location == -1) {
316b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniform(location=%d)",
317b8e80941Smrg                     location);
318b8e80941Smrg      }
319b8e80941Smrg
320848b8605Smrg      return;
321b8e80941Smrg   }
322848b8605Smrg
323848b8605Smrg   {
324b8e80941Smrg      unsigned elements = uni->type->components();
325b8e80941Smrg      const int rmul = glsl_base_type_is_64bit(returnType) ? 2 : 1;
326b8e80941Smrg      int dmul = (uni->type->is_64bit()) ? 2 : 1;
327b8e80941Smrg
328b8e80941Smrg      if ((uni->type->is_sampler() || uni->type->is_image()) &&
329b8e80941Smrg          !uni->is_bindless) {
330b8e80941Smrg         /* Non-bindless samplers/images are represented using unsigned integer
331b8e80941Smrg          * 32-bit, while bindless handles are 64-bit.
332b8e80941Smrg          */
333b8e80941Smrg         dmul = 1;
334b8e80941Smrg      }
335848b8605Smrg
336848b8605Smrg      /* Calculate the source base address *BEFORE* modifying elements to
337848b8605Smrg       * account for the size of the user's buffer.
338848b8605Smrg       */
339b8e80941Smrg      const union gl_constant_value *src;
340b8e80941Smrg      if (ctx->Const.PackedDriverUniformStorage &&
341b8e80941Smrg          (uni->is_bindless || !uni->type->contains_opaque())) {
342b8e80941Smrg         src = (gl_constant_value *) uni->driver_storage[0].data +
343b8e80941Smrg            (offset * elements * dmul);
344b8e80941Smrg      } else {
345b8e80941Smrg         src = &uni->storage[offset * elements * dmul];
346b8e80941Smrg      }
347848b8605Smrg
348848b8605Smrg      assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
349b8e80941Smrg             returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE ||
350b8e80941Smrg             returnType == GLSL_TYPE_UINT64 || returnType == GLSL_TYPE_INT64);
351b8e80941Smrg
352b8e80941Smrg      /* doubles have a different size than the other 3 types */
353b8e80941Smrg      unsigned bytes = sizeof(src[0]) * elements * rmul;
354848b8605Smrg      if (bufSize < 0 || bytes > (unsigned) bufSize) {
355b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
356b8e80941Smrg                     "glGetnUniform*vARB(out of bounds: bufSize is %d,"
357b8e80941Smrg                     " but %u bytes are required)", bufSize, bytes);
358b8e80941Smrg         return;
359848b8605Smrg      }
360848b8605Smrg
361848b8605Smrg      /* If the return type and the uniform's native type are "compatible,"
362848b8605Smrg       * just memcpy the data.  If the types are not compatible, perform a
363848b8605Smrg       * slower convert-and-copy process.
364848b8605Smrg       */
365b8e80941Smrg      if (returnType == uni->type->base_type ||
366b8e80941Smrg          ((returnType == GLSL_TYPE_INT || returnType == GLSL_TYPE_UINT) &&
367b8e80941Smrg           (uni->type->is_sampler() || uni->type->is_image())) ||
368b8e80941Smrg          (returnType == GLSL_TYPE_UINT64 && uni->is_bindless)) {
369b8e80941Smrg         memcpy(paramsOut, src, bytes);
370848b8605Smrg      } else {
371b8e80941Smrg         union gl_constant_value *const dst =
372b8e80941Smrg            (union gl_constant_value *) paramsOut;
373b8e80941Smrg         /* This code could be optimized by putting the loop inside the switch
374b8e80941Smrg          * statements.  However, this is not expected to be
375b8e80941Smrg          * performance-critical code.
376b8e80941Smrg          */
377b8e80941Smrg         for (unsigned i = 0; i < elements; i++) {
378b8e80941Smrg            int sidx = i * dmul;
379b8e80941Smrg            int didx = i * rmul;
380b8e80941Smrg
381b8e80941Smrg            switch (returnType) {
382b8e80941Smrg            case GLSL_TYPE_FLOAT:
383b8e80941Smrg               switch (uni->type->base_type) {
384b8e80941Smrg               case GLSL_TYPE_UINT:
385b8e80941Smrg                  dst[didx].f = (float) src[sidx].u;
386b8e80941Smrg                  break;
387b8e80941Smrg               case GLSL_TYPE_INT:
388b8e80941Smrg               case GLSL_TYPE_SAMPLER:
389b8e80941Smrg               case GLSL_TYPE_IMAGE:
390b8e80941Smrg                  dst[didx].f = (float) src[sidx].i;
391b8e80941Smrg                  break;
392b8e80941Smrg               case GLSL_TYPE_BOOL:
393b8e80941Smrg                  dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
394b8e80941Smrg                  break;
395b8e80941Smrg               case GLSL_TYPE_DOUBLE: {
396b8e80941Smrg                  double tmp;
397b8e80941Smrg                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
398b8e80941Smrg                  dst[didx].f = tmp;
399b8e80941Smrg                  break;
400b8e80941Smrg               }
401b8e80941Smrg               case GLSL_TYPE_UINT64: {
402b8e80941Smrg                  uint64_t tmp;
403b8e80941Smrg                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
404b8e80941Smrg                  dst[didx].f = tmp;
405b8e80941Smrg                  break;
406b8e80941Smrg                }
407b8e80941Smrg               case GLSL_TYPE_INT64: {
408b8e80941Smrg                  uint64_t tmp;
409b8e80941Smrg                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
410b8e80941Smrg                  dst[didx].f = tmp;
411b8e80941Smrg                  break;
412b8e80941Smrg               }
413b8e80941Smrg               default:
414b8e80941Smrg                  assert(!"Should not get here.");
415b8e80941Smrg                  break;
416b8e80941Smrg               }
417b8e80941Smrg               break;
418b8e80941Smrg
419b8e80941Smrg            case GLSL_TYPE_DOUBLE:
420b8e80941Smrg               switch (uni->type->base_type) {
421b8e80941Smrg               case GLSL_TYPE_UINT: {
422b8e80941Smrg                  double tmp = src[sidx].u;
423b8e80941Smrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
424b8e80941Smrg                  break;
425b8e80941Smrg               }
426b8e80941Smrg               case GLSL_TYPE_INT:
427b8e80941Smrg               case GLSL_TYPE_SAMPLER:
428b8e80941Smrg               case GLSL_TYPE_IMAGE: {
429b8e80941Smrg                  double tmp = src[sidx].i;
430b8e80941Smrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
431b8e80941Smrg                  break;
432b8e80941Smrg               }
433b8e80941Smrg               case GLSL_TYPE_BOOL: {
434b8e80941Smrg                  double tmp = src[sidx].i ? 1.0 : 0.0;
435b8e80941Smrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
436b8e80941Smrg                  break;
437b8e80941Smrg               }
438b8e80941Smrg               case GLSL_TYPE_FLOAT: {
439b8e80941Smrg                  double tmp = src[sidx].f;
440b8e80941Smrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
441b8e80941Smrg                  break;
442b8e80941Smrg               }
443b8e80941Smrg               case GLSL_TYPE_UINT64: {
444b8e80941Smrg                  uint64_t tmpu;
445b8e80941Smrg                  double tmp;
446b8e80941Smrg                  memcpy(&tmpu, &src[sidx].u, sizeof(tmpu));
447b8e80941Smrg                  tmp = tmpu;
448b8e80941Smrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
449b8e80941Smrg                  break;
450b8e80941Smrg               }
451b8e80941Smrg               case GLSL_TYPE_INT64: {
452b8e80941Smrg                  int64_t tmpi;
453b8e80941Smrg                  double tmp;
454b8e80941Smrg                  memcpy(&tmpi, &src[sidx].i, sizeof(tmpi));
455b8e80941Smrg                  tmp = tmpi;
456b8e80941Smrg                  memcpy(&dst[didx].f, &tmp, sizeof(tmp));
457b8e80941Smrg                  break;
458b8e80941Smrg               }
459b8e80941Smrg               default:
460b8e80941Smrg                  assert(!"Should not get here.");
461b8e80941Smrg                  break;
462b8e80941Smrg               }
463b8e80941Smrg               break;
464b8e80941Smrg
465b8e80941Smrg            case GLSL_TYPE_INT:
466b8e80941Smrg               switch (uni->type->base_type) {
467b8e80941Smrg               case GLSL_TYPE_FLOAT:
468b8e80941Smrg                  /* While the GL 3.2 core spec doesn't explicitly
469b8e80941Smrg                   * state how conversion of float uniforms to integer
470b8e80941Smrg                   * values works, in section 6.2 "State Tables" on
471b8e80941Smrg                   * page 267 it says:
472b8e80941Smrg                   *
473b8e80941Smrg                   *     "Unless otherwise specified, when floating
474b8e80941Smrg                   *      point state is returned as integer values or
475b8e80941Smrg                   *      integer state is returned as floating-point
476b8e80941Smrg                   *      values it is converted in the fashion
477b8e80941Smrg                   *      described in section 6.1.2"
478b8e80941Smrg                   *
479b8e80941Smrg                   * That section, on page 248, says:
480b8e80941Smrg                   *
481b8e80941Smrg                   *     "If GetIntegerv or GetInteger64v are called,
482b8e80941Smrg                   *      a floating-point value is rounded to the
483b8e80941Smrg                   *      nearest integer..."
484b8e80941Smrg                   */
485b8e80941Smrg                  dst[didx].i = (int64_t) roundf(src[sidx].f);
486b8e80941Smrg                  break;
487b8e80941Smrg               case GLSL_TYPE_BOOL:
488b8e80941Smrg                  dst[didx].i = src[sidx].i ? 1 : 0;
489b8e80941Smrg                  break;
490b8e80941Smrg               case GLSL_TYPE_UINT:
491b8e80941Smrg                  dst[didx].i = MIN2(src[sidx].i, INT_MAX);
492b8e80941Smrg                  break;
493b8e80941Smrg               case GLSL_TYPE_DOUBLE: {
494b8e80941Smrg                  double tmp;
495b8e80941Smrg                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
496b8e80941Smrg                  dst[didx].i = (int64_t) round(tmp);
497b8e80941Smrg                  break;
498b8e80941Smrg               }
499b8e80941Smrg               case GLSL_TYPE_UINT64: {
500b8e80941Smrg                  uint64_t tmp;
501b8e80941Smrg                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
502b8e80941Smrg                  dst[didx].i = tmp;
503b8e80941Smrg                  break;
504b8e80941Smrg               }
505b8e80941Smrg               case GLSL_TYPE_INT64: {
506b8e80941Smrg                  int64_t tmp;
507b8e80941Smrg                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
508b8e80941Smrg                  dst[didx].i = tmp;
509b8e80941Smrg                  break;
510b8e80941Smrg               }
511b8e80941Smrg               default:
512b8e80941Smrg                  assert(!"Should not get here.");
513b8e80941Smrg                  break;
514b8e80941Smrg               }
515b8e80941Smrg               break;
516b8e80941Smrg
517b8e80941Smrg            case GLSL_TYPE_UINT:
518b8e80941Smrg               switch (uni->type->base_type) {
519b8e80941Smrg               case GLSL_TYPE_FLOAT:
520b8e80941Smrg                  /* The spec isn't terribly clear how to handle negative
521b8e80941Smrg                   * values with an unsigned return type.
522b8e80941Smrg                   *
523b8e80941Smrg                   * GL 4.5 section 2.2.2 ("Data Conversions for State
524b8e80941Smrg                   * Query Commands") says:
525b8e80941Smrg                   *
526b8e80941Smrg                   * "If a value is so large in magnitude that it cannot be
527b8e80941Smrg                   *  represented by the returned data type, then the nearest
528b8e80941Smrg                   *  value representable using the requested type is
529b8e80941Smrg                   *  returned."
530b8e80941Smrg                   */
531b8e80941Smrg                  dst[didx].u = src[sidx].f < 0.0f ?
532b8e80941Smrg                     0u : (uint32_t) roundf(src[sidx].f);
533b8e80941Smrg                  break;
534b8e80941Smrg               case GLSL_TYPE_BOOL:
535b8e80941Smrg                  dst[didx].i = src[sidx].i ? 1 : 0;
536b8e80941Smrg                  break;
537b8e80941Smrg               case GLSL_TYPE_INT:
538b8e80941Smrg                  dst[didx].i = MAX2(src[sidx].i, 0);
539b8e80941Smrg                  break;
540b8e80941Smrg               case GLSL_TYPE_DOUBLE: {
541b8e80941Smrg                  double tmp;
542b8e80941Smrg                  memcpy(&tmp, &src[sidx].f, sizeof(tmp));
543b8e80941Smrg                  dst[didx].u = tmp < 0.0 ? 0u : (uint32_t) round(tmp);
544b8e80941Smrg                  break;
545b8e80941Smrg               }
546b8e80941Smrg               case GLSL_TYPE_UINT64: {
547b8e80941Smrg                  uint64_t tmp;
548b8e80941Smrg                  memcpy(&tmp, &src[sidx].u, sizeof(tmp));
549b8e80941Smrg                  dst[didx].i = MIN2(tmp, INT_MAX);
550b8e80941Smrg                  break;
551b8e80941Smrg               }
552b8e80941Smrg               case GLSL_TYPE_INT64: {
553b8e80941Smrg                  int64_t tmp;
554b8e80941Smrg                  memcpy(&tmp, &src[sidx].i, sizeof(tmp));
555b8e80941Smrg                  dst[didx].i = MAX2(tmp, 0);
556b8e80941Smrg                  break;
557b8e80941Smrg               }
558b8e80941Smrg               default:
559b8e80941Smrg                  unreachable("invalid uniform type");
560b8e80941Smrg               }
561b8e80941Smrg               break;
562b8e80941Smrg
563b8e80941Smrg            case GLSL_TYPE_INT64:
564b8e80941Smrg               switch (uni->type->base_type) {
565b8e80941Smrg               case GLSL_TYPE_UINT: {
566b8e80941Smrg                  uint64_t tmp = src[sidx].u;
567b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
568b8e80941Smrg                  break;
569b8e80941Smrg               }
570b8e80941Smrg               case GLSL_TYPE_INT:
571b8e80941Smrg               case GLSL_TYPE_SAMPLER:
572b8e80941Smrg               case GLSL_TYPE_IMAGE: {
573b8e80941Smrg                  int64_t tmp = src[sidx].i;
574b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
575b8e80941Smrg                  break;
576b8e80941Smrg               }
577b8e80941Smrg               case GLSL_TYPE_BOOL: {
578b8e80941Smrg                  int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
579b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
580b8e80941Smrg                  break;
581b8e80941Smrg               }
582b8e80941Smrg               case GLSL_TYPE_UINT64: {
583b8e80941Smrg                  uint64_t u64;
584b8e80941Smrg                  memcpy(&u64, &src[sidx].u, sizeof(u64));
585b8e80941Smrg                  int64_t tmp = MIN2(u64, INT_MAX);
586b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
587b8e80941Smrg                  break;
588b8e80941Smrg               }
589b8e80941Smrg               case GLSL_TYPE_FLOAT: {
590b8e80941Smrg                  int64_t tmp = (int64_t) roundf(src[sidx].f);
591b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
592b8e80941Smrg                  break;
593b8e80941Smrg               }
594b8e80941Smrg               case GLSL_TYPE_DOUBLE: {
595b8e80941Smrg                  double d;
596b8e80941Smrg                  memcpy(&d, &src[sidx].f, sizeof(d));
597b8e80941Smrg                  int64_t tmp = (int64_t) round(d);
598b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
599b8e80941Smrg                  break;
600b8e80941Smrg               }
601b8e80941Smrg               default:
602b8e80941Smrg                  assert(!"Should not get here.");
603b8e80941Smrg                  break;
604b8e80941Smrg               }
605b8e80941Smrg               break;
606b8e80941Smrg
607b8e80941Smrg            case GLSL_TYPE_UINT64:
608b8e80941Smrg               switch (uni->type->base_type) {
609b8e80941Smrg               case GLSL_TYPE_UINT: {
610b8e80941Smrg                  uint64_t tmp = src[sidx].u;
611b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
612b8e80941Smrg                  break;
613b8e80941Smrg               }
614b8e80941Smrg               case GLSL_TYPE_INT:
615b8e80941Smrg               case GLSL_TYPE_SAMPLER:
616b8e80941Smrg               case GLSL_TYPE_IMAGE: {
617b8e80941Smrg                  int64_t tmp = MAX2(src[sidx].i, 0);
618b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
619b8e80941Smrg                  break;
620b8e80941Smrg               }
621b8e80941Smrg               case GLSL_TYPE_BOOL: {
622b8e80941Smrg                  int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
623b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
624b8e80941Smrg                  break;
625b8e80941Smrg               }
626b8e80941Smrg               case GLSL_TYPE_INT64: {
627b8e80941Smrg                  uint64_t i64;
628b8e80941Smrg                  memcpy(&i64, &src[sidx].i, sizeof(i64));
629b8e80941Smrg                  uint64_t tmp = MAX2(i64, 0);
630b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
631b8e80941Smrg                  break;
632b8e80941Smrg               }
633b8e80941Smrg               case GLSL_TYPE_FLOAT: {
634b8e80941Smrg                  uint64_t tmp = src[sidx].f < 0.0f ?
635b8e80941Smrg                     0ull : (uint64_t) roundf(src[sidx].f);
636b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
637b8e80941Smrg                  break;
638b8e80941Smrg               }
639b8e80941Smrg               case GLSL_TYPE_DOUBLE: {
640b8e80941Smrg                  double d;
641b8e80941Smrg                  memcpy(&d, &src[sidx].f, sizeof(d));
642b8e80941Smrg                  uint64_t tmp = (d < 0.0) ? 0ull : (uint64_t) round(d);
643b8e80941Smrg                  memcpy(&dst[didx].u, &tmp, sizeof(tmp));
644b8e80941Smrg                  break;
645b8e80941Smrg               }
646b8e80941Smrg               default:
647b8e80941Smrg                  assert(!"Should not get here.");
648b8e80941Smrg                  break;
649b8e80941Smrg               }
650b8e80941Smrg               break;
651b8e80941Smrg
652b8e80941Smrg            default:
653b8e80941Smrg               assert(!"Should not get here.");
654b8e80941Smrg               break;
655b8e80941Smrg            }
656b8e80941Smrg         }
657848b8605Smrg      }
658848b8605Smrg   }
659848b8605Smrg}
660848b8605Smrg
661848b8605Smrgstatic void
662848b8605Smrglog_uniform(const void *values, enum glsl_base_type basicType,
663848b8605Smrg	    unsigned rows, unsigned cols, unsigned count,
664848b8605Smrg	    bool transpose,
665848b8605Smrg	    const struct gl_shader_program *shProg,
666848b8605Smrg	    GLint location,
667848b8605Smrg	    const struct gl_uniform_storage *uni)
668848b8605Smrg{
669848b8605Smrg
670848b8605Smrg   const union gl_constant_value *v = (const union gl_constant_value *) values;
671848b8605Smrg   const unsigned elems = rows * cols * count;
672848b8605Smrg   const char *const extra = (cols == 1) ? "uniform" : "uniform matrix";
673848b8605Smrg
674848b8605Smrg   printf("Mesa: set program %u %s \"%s\" (loc %d, type \"%s\", "
675848b8605Smrg	  "transpose = %s) to: ",
676848b8605Smrg	  shProg->Name, extra, uni->name, location, uni->type->name,
677848b8605Smrg	  transpose ? "true" : "false");
678848b8605Smrg   for (unsigned i = 0; i < elems; i++) {
679848b8605Smrg      if (i != 0 && ((i % rows) == 0))
680848b8605Smrg	 printf(", ");
681848b8605Smrg
682848b8605Smrg      switch (basicType) {
683848b8605Smrg      case GLSL_TYPE_UINT:
684848b8605Smrg	 printf("%u ", v[i].u);
685848b8605Smrg	 break;
686848b8605Smrg      case GLSL_TYPE_INT:
687848b8605Smrg	 printf("%d ", v[i].i);
688848b8605Smrg	 break;
689b8e80941Smrg      case GLSL_TYPE_UINT64: {
690b8e80941Smrg         uint64_t tmp;
691b8e80941Smrg         memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
692b8e80941Smrg         printf("%" PRIu64 " ", tmp);
693b8e80941Smrg         break;
694b8e80941Smrg      }
695b8e80941Smrg      case GLSL_TYPE_INT64: {
696b8e80941Smrg         int64_t tmp;
697b8e80941Smrg         memcpy(&tmp, &v[i * 2].u, sizeof(tmp));
698b8e80941Smrg         printf("%" PRId64 " ", tmp);
699b8e80941Smrg         break;
700b8e80941Smrg      }
701848b8605Smrg      case GLSL_TYPE_FLOAT:
702848b8605Smrg	 printf("%g ", v[i].f);
703848b8605Smrg	 break;
704b8e80941Smrg      case GLSL_TYPE_DOUBLE: {
705b8e80941Smrg         double tmp;
706b8e80941Smrg         memcpy(&tmp, &v[i * 2].f, sizeof(tmp));
707b8e80941Smrg         printf("%g ", tmp);
708b8e80941Smrg         break;
709b8e80941Smrg      }
710848b8605Smrg      default:
711848b8605Smrg	 assert(!"Should not get here.");
712848b8605Smrg	 break;
713848b8605Smrg      }
714848b8605Smrg   }
715848b8605Smrg   printf("\n");
716848b8605Smrg   fflush(stdout);
717848b8605Smrg}
718848b8605Smrg
719848b8605Smrg#if 0
720848b8605Smrgstatic void
721848b8605Smrglog_program_parameters(const struct gl_shader_program *shProg)
722848b8605Smrg{
723848b8605Smrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
724848b8605Smrg      if (shProg->_LinkedShaders[i] == NULL)
725848b8605Smrg	 continue;
726848b8605Smrg
727848b8605Smrg      const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
728848b8605Smrg
729848b8605Smrg      printf("Program %d %s shader parameters:\n",
730848b8605Smrg             shProg->Name, _mesa_shader_stage_to_string(i));
731848b8605Smrg      for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
732b8e80941Smrg         unsigned pvo = prog->Parameters->ParameterValueOffset[j];
733b8e80941Smrg         printf("%s: %u %p %f %f %f %f\n",
734848b8605Smrg		prog->Parameters->Parameters[j].Name,
735b8e80941Smrg                pvo,
736b8e80941Smrg                prog->Parameters->ParameterValues + pvo,
737b8e80941Smrg                prog->Parameters->ParameterValues[pvo].f,
738b8e80941Smrg                prog->Parameters->ParameterValues[pvo + 1].f,
739b8e80941Smrg                prog->Parameters->ParameterValues[pvo + 2].f,
740b8e80941Smrg                prog->Parameters->ParameterValues[pvo + 3].f);
741848b8605Smrg      }
742848b8605Smrg   }
743848b8605Smrg   fflush(stdout);
744848b8605Smrg}
745848b8605Smrg#endif
746848b8605Smrg
747848b8605Smrg/**
748848b8605Smrg * Propagate some values from uniform backing storage to driver storage
749848b8605Smrg *
750848b8605Smrg * Values propagated from uniform backing storage to driver storage
751848b8605Smrg * have all format / type conversions previously requested by the
752848b8605Smrg * driver applied.  This function is most often called by the
753848b8605Smrg * implementations of \c glUniform1f, etc. and \c glUniformMatrix2f,
754848b8605Smrg * etc.
755848b8605Smrg *
756848b8605Smrg * \param uni          Uniform whose data is to be propagated to driver storage
757848b8605Smrg * \param array_index  If \c uni is an array, this is the element of
758848b8605Smrg *                     the array to be propagated.
759848b8605Smrg * \param count        Number of array elements to propagate.
760848b8605Smrg */
761848b8605Smrgextern "C" void
762848b8605Smrg_mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
763848b8605Smrg					   unsigned array_index,
764848b8605Smrg					   unsigned count)
765848b8605Smrg{
766848b8605Smrg   unsigned i;
767848b8605Smrg
768b8e80941Smrg   const unsigned components = uni->type->vector_elements;
769b8e80941Smrg   const unsigned vectors = uni->type->matrix_columns;
770b8e80941Smrg   const int dmul = uni->type->is_64bit() ? 2 : 1;
771848b8605Smrg
772848b8605Smrg   /* Store the data in the driver's requested type in the driver's storage
773848b8605Smrg    * areas.
774848b8605Smrg    */
775b8e80941Smrg   unsigned src_vector_byte_stride = components * 4 * dmul;
776848b8605Smrg
777848b8605Smrg   for (i = 0; i < uni->num_driver_storage; i++) {
778848b8605Smrg      struct gl_uniform_driver_storage *const store = &uni->driver_storage[i];
779848b8605Smrg      uint8_t *dst = (uint8_t *) store->data;
780848b8605Smrg      const unsigned extra_stride =
781848b8605Smrg	 store->element_stride - (vectors * store->vector_stride);
782848b8605Smrg      const uint8_t *src =
783b8e80941Smrg	 (uint8_t *) (&uni->storage[array_index * (dmul * components * vectors)].i);
784848b8605Smrg
785848b8605Smrg#if 0
786848b8605Smrg      printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
787848b8605Smrg	     "extra_stride=%u\n",
788848b8605Smrg	     __func__, dst, array_index, components,
789848b8605Smrg	     vectors, count, store->vector_stride, extra_stride);
790848b8605Smrg#endif
791848b8605Smrg
792848b8605Smrg      dst += array_index * store->element_stride;
793848b8605Smrg
794848b8605Smrg      switch (store->format) {
795b8e80941Smrg      case uniform_native: {
796848b8605Smrg	 unsigned j;
797848b8605Smrg	 unsigned v;
798848b8605Smrg
799b8e80941Smrg	 if (src_vector_byte_stride == store->vector_stride) {
800b8e80941Smrg	    if (extra_stride) {
801b8e80941Smrg	       for (j = 0; j < count; j++) {
802b8e80941Smrg	          memcpy(dst, src, src_vector_byte_stride * vectors);
803b8e80941Smrg	          src += src_vector_byte_stride * vectors;
804b8e80941Smrg	          dst += store->vector_stride * vectors;
805848b8605Smrg
806b8e80941Smrg	          dst += extra_stride;
807848b8605Smrg	       }
808b8e80941Smrg	    } else {
809b8e80941Smrg	       /* Unigine Heaven benchmark gets here */
810b8e80941Smrg	       memcpy(dst, src, src_vector_byte_stride * vectors * count);
811b8e80941Smrg	       src += src_vector_byte_stride * vectors * count;
812b8e80941Smrg	       dst += store->vector_stride * vectors * count;
813848b8605Smrg	    }
814b8e80941Smrg	 } else {
815b8e80941Smrg	    for (j = 0; j < count; j++) {
816b8e80941Smrg	       for (v = 0; v < vectors; v++) {
817b8e80941Smrg	          memcpy(dst, src, src_vector_byte_stride);
818b8e80941Smrg	          src += src_vector_byte_stride;
819b8e80941Smrg	          dst += store->vector_stride;
820b8e80941Smrg	       }
821848b8605Smrg
822b8e80941Smrg	       dst += extra_stride;
823b8e80941Smrg	    }
824848b8605Smrg	 }
825848b8605Smrg	 break;
826848b8605Smrg      }
827848b8605Smrg
828b8e80941Smrg      case uniform_int_float: {
829848b8605Smrg	 const int *isrc = (const int *) src;
830848b8605Smrg	 unsigned j;
831848b8605Smrg	 unsigned v;
832848b8605Smrg	 unsigned c;
833848b8605Smrg
834848b8605Smrg	 for (j = 0; j < count; j++) {
835848b8605Smrg	    for (v = 0; v < vectors; v++) {
836848b8605Smrg	       for (c = 0; c < components; c++) {
837b8e80941Smrg		  ((float *) dst)[c] = (float) *isrc;
838848b8605Smrg		  isrc++;
839848b8605Smrg	       }
840848b8605Smrg
841848b8605Smrg	       dst += store->vector_stride;
842848b8605Smrg	    }
843848b8605Smrg
844848b8605Smrg	    dst += extra_stride;
845848b8605Smrg	 }
846848b8605Smrg	 break;
847848b8605Smrg      }
848848b8605Smrg
849848b8605Smrg      default:
850848b8605Smrg	 assert(!"Should not get here.");
851848b8605Smrg	 break;
852848b8605Smrg      }
853848b8605Smrg   }
854848b8605Smrg}
855848b8605Smrg
856b8e80941Smrg
857848b8605Smrg/**
858b8e80941Smrg * Return printable string for a given GLSL_TYPE_x
859848b8605Smrg */
860b8e80941Smrgstatic const char *
861b8e80941Smrgglsl_type_name(enum glsl_base_type type)
862848b8605Smrg{
863b8e80941Smrg   switch (type) {
864b8e80941Smrg   case GLSL_TYPE_UINT:
865b8e80941Smrg      return "uint";
866b8e80941Smrg   case GLSL_TYPE_INT:
867b8e80941Smrg      return "int";
868b8e80941Smrg   case GLSL_TYPE_FLOAT:
869b8e80941Smrg      return "float";
870b8e80941Smrg   case GLSL_TYPE_DOUBLE:
871b8e80941Smrg      return "double";
872b8e80941Smrg   case GLSL_TYPE_UINT64:
873b8e80941Smrg      return "uint64";
874b8e80941Smrg   case GLSL_TYPE_INT64:
875b8e80941Smrg      return "int64";
876b8e80941Smrg   case GLSL_TYPE_BOOL:
877b8e80941Smrg      return "bool";
878b8e80941Smrg   case GLSL_TYPE_SAMPLER:
879b8e80941Smrg      return "sampler";
880b8e80941Smrg   case GLSL_TYPE_IMAGE:
881b8e80941Smrg      return "image";
882b8e80941Smrg   case GLSL_TYPE_ATOMIC_UINT:
883b8e80941Smrg      return "atomic_uint";
884b8e80941Smrg   case GLSL_TYPE_STRUCT:
885b8e80941Smrg      return "struct";
886b8e80941Smrg   case GLSL_TYPE_INTERFACE:
887b8e80941Smrg      return "interface";
888b8e80941Smrg   case GLSL_TYPE_ARRAY:
889b8e80941Smrg      return "array";
890b8e80941Smrg   case GLSL_TYPE_VOID:
891b8e80941Smrg      return "void";
892b8e80941Smrg   case GLSL_TYPE_ERROR:
893b8e80941Smrg      return "error";
894b8e80941Smrg   default:
895b8e80941Smrg      return "other";
896b8e80941Smrg   }
897b8e80941Smrg}
898848b8605Smrg
899b8e80941Smrg
900b8e80941Smrgstatic struct gl_uniform_storage *
901b8e80941Smrgvalidate_uniform(GLint location, GLsizei count, const GLvoid *values,
902b8e80941Smrg                 unsigned *offset, struct gl_context *ctx,
903b8e80941Smrg                 struct gl_shader_program *shProg,
904b8e80941Smrg                 enum glsl_base_type basicType, unsigned src_components)
905b8e80941Smrg{
906848b8605Smrg   struct gl_uniform_storage *const uni =
907b8e80941Smrg      validate_uniform_parameters(location, count, offset,
908b8e80941Smrg                                  ctx, shProg, "glUniform");
909848b8605Smrg   if (uni == NULL)
910b8e80941Smrg      return NULL;
911848b8605Smrg
912b8e80941Smrg   if (uni->type->is_matrix()) {
913b8e80941Smrg      /* Can't set matrix uniforms (like mat4) with glUniform */
914b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
915b8e80941Smrg                  "glUniform%u(uniform \"%s\"@%d is matrix)",
916b8e80941Smrg                  src_components, uni->name, location);
917b8e80941Smrg      return NULL;
918848b8605Smrg   }
919848b8605Smrg
920b8e80941Smrg   /* Verify that the types are compatible. */
921b8e80941Smrg   const unsigned components = uni->type->vector_elements;
922b8e80941Smrg
923b8e80941Smrg   if (components != src_components) {
924b8e80941Smrg      /* glUniformN() must match float/vecN type */
925b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
926b8e80941Smrg                  "glUniform%u(\"%s\"@%u has %u components, not %u)",
927b8e80941Smrg                  src_components, uni->name, location,
928b8e80941Smrg                  components, src_components);
929b8e80941Smrg      return NULL;
930848b8605Smrg   }
931848b8605Smrg
932848b8605Smrg   bool match;
933848b8605Smrg   switch (uni->type->base_type) {
934848b8605Smrg   case GLSL_TYPE_BOOL:
935b8e80941Smrg      match = (basicType != GLSL_TYPE_DOUBLE);
936848b8605Smrg      break;
937848b8605Smrg   case GLSL_TYPE_SAMPLER:
938848b8605Smrg      match = (basicType == GLSL_TYPE_INT);
939848b8605Smrg      break;
940b8e80941Smrg   case GLSL_TYPE_IMAGE:
941b8e80941Smrg      match = (basicType == GLSL_TYPE_INT && _mesa_is_desktop_gl(ctx));
942b8e80941Smrg      break;
943848b8605Smrg   default:
944848b8605Smrg      match = (basicType == uni->type->base_type);
945848b8605Smrg      break;
946848b8605Smrg   }
947848b8605Smrg
948b8e80941Smrg   if (!match) {
949b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
950b8e80941Smrg                  "glUniform%u(\"%s\"@%d is %s, not %s)",
951b8e80941Smrg                  src_components, uni->name, location,
952b8e80941Smrg                  glsl_type_name(uni->type->base_type),
953b8e80941Smrg                  glsl_type_name(basicType));
954b8e80941Smrg      return NULL;
955848b8605Smrg   }
956848b8605Smrg
957b8e80941Smrg   if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
958848b8605Smrg      log_uniform(values, basicType, components, 1, count,
959b8e80941Smrg                  false, shProg, location, uni);
960848b8605Smrg   }
961848b8605Smrg
962848b8605Smrg   /* Page 100 (page 116 of the PDF) of the OpenGL 3.0 spec says:
963848b8605Smrg    *
964848b8605Smrg    *     "Setting a sampler's value to i selects texture image unit number
965848b8605Smrg    *     i. The values of i range from zero to the implementation- dependent
966848b8605Smrg    *     maximum supported number of texture image units."
967848b8605Smrg    *
968848b8605Smrg    * In addition, table 2.3, "Summary of GL errors," on page 17 (page 33 of
969848b8605Smrg    * the PDF) says:
970848b8605Smrg    *
971848b8605Smrg    *     "Error         Description                    Offending command
972848b8605Smrg    *                                                   ignored?
973848b8605Smrg    *     ...
974848b8605Smrg    *     INVALID_VALUE  Numeric argument out of range  Yes"
975848b8605Smrg    *
976848b8605Smrg    * Based on that, when an invalid sampler is specified, we generate a
977848b8605Smrg    * GL_INVALID_VALUE error and ignore the command.
978848b8605Smrg    */
979848b8605Smrg   if (uni->type->is_sampler()) {
980b8e80941Smrg      for (int i = 0; i < count; i++) {
981b8e80941Smrg         const unsigned texUnit = ((unsigned *) values)[i];
982848b8605Smrg
983848b8605Smrg         /* check that the sampler (tex unit index) is legal */
984848b8605Smrg         if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
985848b8605Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
986848b8605Smrg                        "glUniform1i(invalid sampler/tex unit index for "
987b8e80941Smrg                        "uniform %d)", location);
988b8e80941Smrg            return NULL;
989848b8605Smrg         }
990848b8605Smrg      }
991b8e80941Smrg      /* We need to reset the validate flag on changes to samplers in case
992b8e80941Smrg       * two different sampler types are set to the same texture unit.
993b8e80941Smrg       */
994b8e80941Smrg      ctx->_Shader->Validated = GL_FALSE;
995848b8605Smrg   }
996848b8605Smrg
997848b8605Smrg   if (uni->type->is_image()) {
998b8e80941Smrg      for (int i = 0; i < count; i++) {
999848b8605Smrg         const int unit = ((GLint *) values)[i];
1000848b8605Smrg
1001848b8605Smrg         /* check that the image unit is legal */
1002848b8605Smrg         if (unit < 0 || unit >= (int)ctx->Const.MaxImageUnits) {
1003848b8605Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
1004848b8605Smrg                        "glUniform1i(invalid image unit index for uniform %d)",
1005848b8605Smrg                        location);
1006b8e80941Smrg            return NULL;
1007848b8605Smrg         }
1008848b8605Smrg      }
1009848b8605Smrg   }
1010848b8605Smrg
1011b8e80941Smrg   return uni;
1012b8e80941Smrg}
1013b8e80941Smrg
1014b8e80941Smrgvoid
1015b8e80941Smrg_mesa_flush_vertices_for_uniforms(struct gl_context *ctx,
1016b8e80941Smrg                                  const struct gl_uniform_storage *uni)
1017b8e80941Smrg{
1018b8e80941Smrg   /* Opaque uniforms have no storage unless they are bindless */
1019b8e80941Smrg   if (!uni->is_bindless && uni->type->contains_opaque()) {
1020b8e80941Smrg      FLUSH_VERTICES(ctx, 0);
1021b8e80941Smrg      return;
1022b8e80941Smrg   }
1023b8e80941Smrg
1024b8e80941Smrg   uint64_t new_driver_state = 0;
1025b8e80941Smrg   unsigned mask = uni->active_shader_mask;
1026b8e80941Smrg
1027b8e80941Smrg   while (mask) {
1028b8e80941Smrg      unsigned index = u_bit_scan(&mask);
1029b8e80941Smrg
1030b8e80941Smrg      assert(index < MESA_SHADER_STAGES);
1031b8e80941Smrg      new_driver_state |= ctx->DriverFlags.NewShaderConstants[index];
1032b8e80941Smrg   }
1033b8e80941Smrg
1034b8e80941Smrg   FLUSH_VERTICES(ctx, new_driver_state ? 0 : _NEW_PROGRAM_CONSTANTS);
1035b8e80941Smrg   ctx->NewDriverState |= new_driver_state;
1036b8e80941Smrg}
1037b8e80941Smrg
1038b8e80941Smrgstatic void
1039b8e80941Smrgcopy_uniforms_to_storage(gl_constant_value *storage,
1040b8e80941Smrg                         struct gl_uniform_storage *uni,
1041b8e80941Smrg                         struct gl_context *ctx, GLsizei count,
1042b8e80941Smrg                         const GLvoid *values, const int size_mul,
1043b8e80941Smrg                         const unsigned offset, const unsigned components,
1044b8e80941Smrg                         enum glsl_base_type basicType)
1045b8e80941Smrg{
1046b8e80941Smrg   if (!uni->type->is_boolean() && !uni->is_bindless) {
1047b8e80941Smrg      memcpy(storage, values,
1048b8e80941Smrg             sizeof(storage[0]) * components * count * size_mul);
1049b8e80941Smrg   } else if (uni->is_bindless) {
1050b8e80941Smrg      const union gl_constant_value *src =
1051b8e80941Smrg         (const union gl_constant_value *) values;
1052b8e80941Smrg      GLuint64 *dst = (GLuint64 *)&storage->i;
1053b8e80941Smrg      const unsigned elems = components * count;
1054b8e80941Smrg
1055b8e80941Smrg      for (unsigned i = 0; i < elems; i++) {
1056b8e80941Smrg         dst[i] = src[i].i;
1057b8e80941Smrg      }
1058b8e80941Smrg   } else {
1059b8e80941Smrg      const union gl_constant_value *src =
1060b8e80941Smrg         (const union gl_constant_value *) values;
1061b8e80941Smrg      union gl_constant_value *dst = storage;
1062b8e80941Smrg      const unsigned elems = components * count;
1063b8e80941Smrg
1064b8e80941Smrg      for (unsigned i = 0; i < elems; i++) {
1065b8e80941Smrg         if (basicType == GLSL_TYPE_FLOAT) {
1066b8e80941Smrg            dst[i].i = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0;
1067b8e80941Smrg         } else {
1068b8e80941Smrg            dst[i].i = src[i].i != 0    ? ctx->Const.UniformBooleanTrue : 0;
1069b8e80941Smrg         }
1070b8e80941Smrg      }
1071b8e80941Smrg   }
1072b8e80941Smrg}
1073b8e80941Smrg
1074b8e80941Smrg
1075b8e80941Smrg/**
1076b8e80941Smrg * Called via glUniform*() functions.
1077b8e80941Smrg */
1078b8e80941Smrgextern "C" void
1079b8e80941Smrg_mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
1080b8e80941Smrg              struct gl_context *ctx, struct gl_shader_program *shProg,
1081b8e80941Smrg              enum glsl_base_type basicType, unsigned src_components)
1082b8e80941Smrg{
1083b8e80941Smrg   unsigned offset;
1084b8e80941Smrg   int size_mul = glsl_base_type_is_64bit(basicType) ? 2 : 1;
1085b8e80941Smrg
1086b8e80941Smrg   struct gl_uniform_storage *uni;
1087b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1088b8e80941Smrg      /* From Seciton 7.6 (UNIFORM VARIABLES) of the OpenGL 4.5 spec:
1089b8e80941Smrg       *
1090b8e80941Smrg       *   "If the value of location is -1, the Uniform* commands will
1091b8e80941Smrg       *   silently ignore the data passed in, and the current uniform values
1092b8e80941Smrg       *   will not be changed.
1093b8e80941Smrg       */
1094b8e80941Smrg      if (location == -1)
1095b8e80941Smrg         return;
1096b8e80941Smrg
1097b8e80941Smrg      uni = shProg->UniformRemapTable[location];
1098b8e80941Smrg
1099b8e80941Smrg      /* The array index specified by the uniform location is just the
1100b8e80941Smrg       * uniform location minus the base location of of the uniform.
1101b8e80941Smrg       */
1102b8e80941Smrg      assert(uni->array_elements > 0 || location == (int)uni->remap_location);
1103b8e80941Smrg      offset = location - uni->remap_location;
1104b8e80941Smrg   } else {
1105b8e80941Smrg      uni = validate_uniform(location, count, values, &offset, ctx, shProg,
1106b8e80941Smrg                             basicType, src_components);
1107b8e80941Smrg      if (!uni)
1108b8e80941Smrg         return;
1109b8e80941Smrg   }
1110b8e80941Smrg
1111b8e80941Smrg   const unsigned components = uni->type->vector_elements;
1112b8e80941Smrg
1113848b8605Smrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
1114848b8605Smrg    *
1115848b8605Smrg    *     "When loading N elements starting at an arbitrary position k in a
1116848b8605Smrg    *     uniform declared as an array, elements k through k + N - 1 in the
1117848b8605Smrg    *     array will be replaced with the new values. Values for any array
1118848b8605Smrg    *     element that exceeds the highest array element index used, as
1119848b8605Smrg    *     reported by GetActiveUniform, will be ignored by the GL."
1120848b8605Smrg    *
1121848b8605Smrg    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
1122848b8605Smrg    * will have already generated an error.
1123848b8605Smrg    */
1124848b8605Smrg   if (uni->array_elements != 0) {
1125848b8605Smrg      count = MIN2(count, (int) (uni->array_elements - offset));
1126848b8605Smrg   }
1127848b8605Smrg
1128b8e80941Smrg   /* We check samplers for changes and flush if needed in the sampler
1129b8e80941Smrg    * handling code further down, so just skip them here.
1130b8e80941Smrg    */
1131b8e80941Smrg   if (!uni->type->is_sampler()) {
1132b8e80941Smrg       _mesa_flush_vertices_for_uniforms(ctx, uni);
1133b8e80941Smrg   }
1134848b8605Smrg
1135848b8605Smrg   /* Store the data in the "actual type" backing storage for the uniform.
1136848b8605Smrg    */
1137b8e80941Smrg   gl_constant_value *storage;
1138b8e80941Smrg   if (ctx->Const.PackedDriverUniformStorage &&
1139b8e80941Smrg       (uni->is_bindless || !uni->type->contains_opaque())) {
1140b8e80941Smrg      for (unsigned s = 0; s < uni->num_driver_storage; s++) {
1141b8e80941Smrg         storage = (gl_constant_value *)
1142b8e80941Smrg            uni->driver_storage[s].data + (size_mul * offset * components);
1143b8e80941Smrg
1144b8e80941Smrg         copy_uniforms_to_storage(storage, uni, ctx, count, values, size_mul,
1145b8e80941Smrg                                  offset, components, basicType);
1146b8e80941Smrg      }
1147848b8605Smrg   } else {
1148b8e80941Smrg      storage = &uni->storage[size_mul * components * offset];
1149b8e80941Smrg      copy_uniforms_to_storage(storage, uni, ctx, count, values, size_mul,
1150b8e80941Smrg                               offset, components, basicType);
1151848b8605Smrg
1152b8e80941Smrg      _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
1153848b8605Smrg   }
1154848b8605Smrg
1155848b8605Smrg   /* If the uniform is a sampler, do the extra magic necessary to propagate
1156848b8605Smrg    * the changes through.
1157848b8605Smrg    */
1158848b8605Smrg   if (uni->type->is_sampler()) {
1159848b8605Smrg      bool flushed = false;
1160848b8605Smrg
1161b8e80941Smrg      shProg->SamplersValidated = GL_TRUE;
1162848b8605Smrg
1163b8e80941Smrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1164b8e80941Smrg         struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
1165848b8605Smrg
1166b8e80941Smrg         /* If the shader stage doesn't use the sampler uniform, skip this. */
1167b8e80941Smrg         if (!uni->opaque[i].active)
1168b8e80941Smrg            continue;
1169848b8605Smrg
1170b8e80941Smrg         bool changed = false;
1171b8e80941Smrg         for (int j = 0; j < count; j++) {
1172b8e80941Smrg            unsigned unit = uni->opaque[i].index + offset + j;
1173b8e80941Smrg            unsigned value = ((unsigned *)values)[j];
1174b8e80941Smrg
1175b8e80941Smrg            if (uni->is_bindless) {
1176b8e80941Smrg               struct gl_bindless_sampler *sampler =
1177b8e80941Smrg                  &sh->Program->sh.BindlessSamplers[unit];
1178b8e80941Smrg
1179b8e80941Smrg               /* Mark this bindless sampler as bound to a texture unit.
1180b8e80941Smrg                */
1181b8e80941Smrg               if (sampler->unit != value || !sampler->bound) {
1182b8e80941Smrg                  sampler->unit = value;
1183b8e80941Smrg                  changed = true;
1184b8e80941Smrg               }
1185b8e80941Smrg               sampler->bound = true;
1186b8e80941Smrg               sh->Program->sh.HasBoundBindlessSampler = true;
1187b8e80941Smrg            } else {
1188b8e80941Smrg               if (sh->Program->SamplerUnits[unit] != value) {
1189b8e80941Smrg                  sh->Program->SamplerUnits[unit] = value;
1190b8e80941Smrg                  changed = true;
1191b8e80941Smrg               }
1192b8e80941Smrg            }
1193b8e80941Smrg         }
1194848b8605Smrg
1195b8e80941Smrg         if (changed) {
1196b8e80941Smrg            if (!flushed) {
1197b8e80941Smrg               FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT | _NEW_PROGRAM);
1198b8e80941Smrg               flushed = true;
1199b8e80941Smrg            }
1200848b8605Smrg
1201b8e80941Smrg            struct gl_program *const prog = sh->Program;
1202b8e80941Smrg            _mesa_update_shader_textures_used(shProg, prog);
1203848b8605Smrg            if (ctx->Driver.SamplerUniformChange)
1204b8e80941Smrg               ctx->Driver.SamplerUniformChange(ctx, prog->Target, prog);
1205b8e80941Smrg         }
1206848b8605Smrg      }
1207848b8605Smrg   }
1208848b8605Smrg
1209848b8605Smrg   /* If the uniform is an image, update the mapping from image
1210848b8605Smrg    * uniforms to image units present in the shader data structure.
1211848b8605Smrg    */
1212848b8605Smrg   if (uni->type->is_image()) {
1213b8e80941Smrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1214b8e80941Smrg         struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
1215848b8605Smrg
1216b8e80941Smrg         /* If the shader stage doesn't use the image uniform, skip this. */
1217b8e80941Smrg         if (!uni->opaque[i].active)
1218b8e80941Smrg            continue;
1219848b8605Smrg
1220b8e80941Smrg         for (int j = 0; j < count; j++) {
1221b8e80941Smrg            unsigned unit = uni->opaque[i].index + offset + j;
1222b8e80941Smrg            unsigned value = ((unsigned *)values)[j];
1223b8e80941Smrg
1224b8e80941Smrg            if (uni->is_bindless) {
1225b8e80941Smrg               struct gl_bindless_image *image =
1226b8e80941Smrg                  &sh->Program->sh.BindlessImages[unit];
1227b8e80941Smrg
1228b8e80941Smrg               /* Mark this bindless image as bound to an image unit.
1229b8e80941Smrg                */
1230b8e80941Smrg               image->unit = value;
1231b8e80941Smrg               image->bound = true;
1232b8e80941Smrg               sh->Program->sh.HasBoundBindlessImage = true;
1233b8e80941Smrg            } else {
1234b8e80941Smrg               sh->Program->sh.ImageUnits[unit] = value;
1235b8e80941Smrg            }
1236848b8605Smrg         }
1237848b8605Smrg      }
1238848b8605Smrg
1239848b8605Smrg      ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
1240848b8605Smrg   }
1241848b8605Smrg}
1242848b8605Smrg
1243b8e80941Smrg
1244b8e80941Smrgstatic void
1245b8e80941Smrgcopy_uniform_matrix_to_storage(gl_constant_value *storage,
1246b8e80941Smrg                               GLsizei count, const void *values,
1247b8e80941Smrg                               const unsigned size_mul, const unsigned offset,
1248b8e80941Smrg                               const unsigned components,
1249b8e80941Smrg                               const unsigned vectors, bool transpose,
1250b8e80941Smrg                               unsigned cols, unsigned rows,
1251b8e80941Smrg                               enum glsl_base_type basicType)
1252b8e80941Smrg{
1253b8e80941Smrg   const unsigned elements = components * vectors;
1254b8e80941Smrg
1255b8e80941Smrg   if (!transpose) {
1256b8e80941Smrg      memcpy(storage, values,
1257b8e80941Smrg             sizeof(storage[0]) * elements * count * size_mul);
1258b8e80941Smrg   } else if (basicType == GLSL_TYPE_FLOAT) {
1259b8e80941Smrg      /* Copy and transpose the matrix.
1260b8e80941Smrg       */
1261b8e80941Smrg      const float *src = (const float *)values;
1262b8e80941Smrg      float *dst = &storage->f;
1263b8e80941Smrg
1264b8e80941Smrg      for (int i = 0; i < count; i++) {
1265b8e80941Smrg         for (unsigned r = 0; r < rows; r++) {
1266b8e80941Smrg            for (unsigned c = 0; c < cols; c++) {
1267b8e80941Smrg               dst[(c * components) + r] = src[c + (r * vectors)];
1268b8e80941Smrg            }
1269b8e80941Smrg         }
1270b8e80941Smrg
1271b8e80941Smrg         dst += elements;
1272b8e80941Smrg         src += elements;
1273b8e80941Smrg      }
1274b8e80941Smrg   } else {
1275b8e80941Smrg      assert(basicType == GLSL_TYPE_DOUBLE);
1276b8e80941Smrg      const double *src = (const double *)values;
1277b8e80941Smrg      double *dst = (double *)&storage->f;
1278b8e80941Smrg
1279b8e80941Smrg      for (int i = 0; i < count; i++) {
1280b8e80941Smrg         for (unsigned r = 0; r < rows; r++) {
1281b8e80941Smrg            for (unsigned c = 0; c < cols; c++) {
1282b8e80941Smrg               dst[(c * components) + r] = src[c + (r * vectors)];
1283b8e80941Smrg            }
1284b8e80941Smrg         }
1285b8e80941Smrg
1286b8e80941Smrg         dst += elements;
1287b8e80941Smrg         src += elements;
1288b8e80941Smrg      }
1289b8e80941Smrg   }
1290b8e80941Smrg}
1291b8e80941Smrg
1292b8e80941Smrg
1293848b8605Smrg/**
1294848b8605Smrg * Called by glUniformMatrix*() functions.
1295848b8605Smrg * Note: cols=2, rows=4  ==>  array[2] of vec4
1296848b8605Smrg */
1297848b8605Smrgextern "C" void
1298b8e80941Smrg_mesa_uniform_matrix(GLint location, GLsizei count,
1299b8e80941Smrg                     GLboolean transpose, const void *values,
1300b8e80941Smrg                     struct gl_context *ctx, struct gl_shader_program *shProg,
1301b8e80941Smrg                     GLuint cols, GLuint rows, enum glsl_base_type basicType)
1302848b8605Smrg{
1303848b8605Smrg   unsigned offset;
1304848b8605Smrg   struct gl_uniform_storage *const uni =
1305b8e80941Smrg      validate_uniform_parameters(location, count, &offset,
1306b8e80941Smrg                                  ctx, shProg, "glUniformMatrix");
1307848b8605Smrg   if (uni == NULL)
1308848b8605Smrg      return;
1309848b8605Smrg
1310848b8605Smrg   if (!uni->type->is_matrix()) {
1311848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1312848b8605Smrg		  "glUniformMatrix(non-matrix uniform)");
1313848b8605Smrg      return;
1314848b8605Smrg   }
1315848b8605Smrg
1316b8e80941Smrg   assert(basicType == GLSL_TYPE_FLOAT || basicType == GLSL_TYPE_DOUBLE);
1317b8e80941Smrg   const unsigned size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
1318b8e80941Smrg
1319848b8605Smrg   assert(!uni->type->is_sampler());
1320b8e80941Smrg   const unsigned vectors = uni->type->matrix_columns;
1321b8e80941Smrg   const unsigned components = uni->type->vector_elements;
1322848b8605Smrg
1323848b8605Smrg   /* Verify that the types are compatible.  This is greatly simplified for
1324848b8605Smrg    * matrices because they can only have a float base type.
1325848b8605Smrg    */
1326848b8605Smrg   if (vectors != cols || components != rows) {
1327848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1328848b8605Smrg		  "glUniformMatrix(matrix size mismatch)");
1329848b8605Smrg      return;
1330848b8605Smrg   }
1331848b8605Smrg
1332848b8605Smrg   /* GL_INVALID_VALUE is generated if `transpose' is not GL_FALSE.
1333b8e80941Smrg    * http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml
1334b8e80941Smrg    */
1335b8e80941Smrg   if (transpose) {
1336b8e80941Smrg      if (ctx->API == API_OPENGLES2 && ctx->Version < 30) {
1337848b8605Smrg	 _mesa_error(ctx, GL_INVALID_VALUE,
1338848b8605Smrg		     "glUniformMatrix(matrix transpose is not GL_FALSE)");
1339848b8605Smrg	 return;
1340848b8605Smrg      }
1341848b8605Smrg   }
1342848b8605Smrg
1343b8e80941Smrg   /* Section 2.11.7 (Uniform Variables) of the OpenGL 4.2 Core Profile spec
1344b8e80941Smrg    * says:
1345b8e80941Smrg    *
1346b8e80941Smrg    *     "If any of the following conditions occur, an INVALID_OPERATION
1347b8e80941Smrg    *     error is generated by the Uniform* commands, and no uniform values
1348b8e80941Smrg    *     are changed:
1349b8e80941Smrg    *
1350b8e80941Smrg    *     ...
1351b8e80941Smrg    *
1352b8e80941Smrg    *     - if the uniform declared in the shader is not of type boolean and
1353b8e80941Smrg    *       the type indicated in the name of the Uniform* command used does
1354b8e80941Smrg    *       not match the type of the uniform"
1355b8e80941Smrg    *
1356b8e80941Smrg    * There are no Boolean matrix types, so we do not need to allow
1357b8e80941Smrg    * GLSL_TYPE_BOOL here (as _mesa_uniform does).
1358b8e80941Smrg    */
1359b8e80941Smrg   if (uni->type->base_type != basicType) {
1360b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1361b8e80941Smrg                  "glUniformMatrix%ux%u(\"%s\"@%d is %s, not %s)",
1362b8e80941Smrg                  cols, rows, uni->name, location,
1363b8e80941Smrg                  glsl_type_name(uni->type->base_type),
1364b8e80941Smrg                  glsl_type_name(basicType));
1365b8e80941Smrg      return;
1366b8e80941Smrg   }
1367b8e80941Smrg
1368b8e80941Smrg   if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
1369b8e80941Smrg      log_uniform(values, uni->type->base_type, components, vectors, count,
1370848b8605Smrg		  bool(transpose), shProg, location, uni);
1371848b8605Smrg   }
1372848b8605Smrg
1373848b8605Smrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
1374848b8605Smrg    *
1375848b8605Smrg    *     "When loading N elements starting at an arbitrary position k in a
1376848b8605Smrg    *     uniform declared as an array, elements k through k + N - 1 in the
1377848b8605Smrg    *     array will be replaced with the new values. Values for any array
1378848b8605Smrg    *     element that exceeds the highest array element index used, as
1379848b8605Smrg    *     reported by GetActiveUniform, will be ignored by the GL."
1380848b8605Smrg    *
1381848b8605Smrg    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
1382848b8605Smrg    * will have already generated an error.
1383848b8605Smrg    */
1384848b8605Smrg   if (uni->array_elements != 0) {
1385848b8605Smrg      count = MIN2(count, (int) (uni->array_elements - offset));
1386848b8605Smrg   }
1387848b8605Smrg
1388b8e80941Smrg   _mesa_flush_vertices_for_uniforms(ctx, uni);
1389848b8605Smrg
1390848b8605Smrg   /* Store the data in the "actual type" backing storage for the uniform.
1391848b8605Smrg    */
1392b8e80941Smrg   gl_constant_value *storage;
1393b8e80941Smrg   const unsigned elements = components * vectors;
1394b8e80941Smrg   if (ctx->Const.PackedDriverUniformStorage) {
1395b8e80941Smrg      for (unsigned s = 0; s < uni->num_driver_storage; s++) {
1396b8e80941Smrg         storage = (gl_constant_value *)
1397b8e80941Smrg            uni->driver_storage[s].data + (size_mul * offset * elements);
1398b8e80941Smrg
1399b8e80941Smrg         copy_uniform_matrix_to_storage(storage, count, values, size_mul,
1400b8e80941Smrg                                        offset, components, vectors,
1401b8e80941Smrg                                        transpose, cols, rows, basicType);
1402b8e80941Smrg      }
1403848b8605Smrg   } else {
1404b8e80941Smrg      storage =  &uni->storage[size_mul * elements * offset];
1405b8e80941Smrg      copy_uniform_matrix_to_storage(storage, count, values, size_mul, offset,
1406b8e80941Smrg                                     components, vectors, transpose, cols,
1407b8e80941Smrg                                     rows, basicType);
1408848b8605Smrg
1409b8e80941Smrg      _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
1410848b8605Smrg   }
1411b8e80941Smrg}
1412b8e80941Smrg
1413b8e80941Smrgstatic void
1414b8e80941Smrgupdate_bound_bindless_sampler_flag(struct gl_program *prog)
1415b8e80941Smrg{
1416b8e80941Smrg   unsigned i;
1417b8e80941Smrg
1418b8e80941Smrg   if (likely(!prog->sh.HasBoundBindlessSampler))
1419b8e80941Smrg      return;
1420848b8605Smrg
1421b8e80941Smrg   for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
1422b8e80941Smrg      struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[i];
1423848b8605Smrg
1424b8e80941Smrg      if (sampler->bound)
1425b8e80941Smrg         return;
1426b8e80941Smrg   }
1427b8e80941Smrg   prog->sh.HasBoundBindlessSampler = false;
1428848b8605Smrg}
1429848b8605Smrg
1430b8e80941Smrgstatic void
1431b8e80941Smrgupdate_bound_bindless_image_flag(struct gl_program *prog)
1432b8e80941Smrg{
1433b8e80941Smrg   unsigned i;
1434b8e80941Smrg
1435b8e80941Smrg   if (likely(!prog->sh.HasBoundBindlessImage))
1436b8e80941Smrg      return;
1437b8e80941Smrg
1438b8e80941Smrg   for (i = 0; i < prog->sh.NumBindlessImages; i++) {
1439b8e80941Smrg      struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
1440b8e80941Smrg
1441b8e80941Smrg      if (image->bound)
1442b8e80941Smrg         return;
1443b8e80941Smrg   }
1444b8e80941Smrg   prog->sh.HasBoundBindlessImage = false;
1445b8e80941Smrg}
1446848b8605Smrg
1447848b8605Smrg/**
1448b8e80941Smrg * Called via glUniformHandleui64*ARB() functions.
1449848b8605Smrg */
1450b8e80941Smrgextern "C" void
1451b8e80941Smrg_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
1452b8e80941Smrg                     struct gl_context *ctx, struct gl_shader_program *shProg)
1453848b8605Smrg{
1454b8e80941Smrg   unsigned offset;
1455b8e80941Smrg   struct gl_uniform_storage *uni;
1456848b8605Smrg
1457b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1458b8e80941Smrg      /* From Section 7.6 (UNIFORM VARIABLES) of the OpenGL 4.5 spec:
1459b8e80941Smrg       *
1460b8e80941Smrg       *   "If the value of location is -1, the Uniform* commands will
1461b8e80941Smrg       *   silently ignore the data passed in, and the current uniform values
1462b8e80941Smrg       *   will not be changed.
1463b8e80941Smrg       */
1464b8e80941Smrg      if (location == -1)
1465b8e80941Smrg         return;
1466848b8605Smrg
1467b8e80941Smrg      uni = shProg->UniformRemapTable[location];
1468b8e80941Smrg
1469b8e80941Smrg      /* The array index specified by the uniform location is just the
1470b8e80941Smrg       * uniform location minus the base location of of the uniform.
1471b8e80941Smrg       */
1472b8e80941Smrg      assert(uni->array_elements > 0 || location == (int)uni->remap_location);
1473b8e80941Smrg      offset = location - uni->remap_location;
1474848b8605Smrg   } else {
1475b8e80941Smrg      uni = validate_uniform_parameters(location, count, &offset,
1476b8e80941Smrg                                        ctx, shProg, "glUniformHandleui64*ARB");
1477b8e80941Smrg      if (!uni)
1478b8e80941Smrg         return;
1479b8e80941Smrg
1480b8e80941Smrg      if (!uni->is_bindless) {
1481b8e80941Smrg         /* From section "Errors" of the ARB_bindless_texture spec:
1482b8e80941Smrg          *
1483b8e80941Smrg          * "The error INVALID_OPERATION is generated by
1484b8e80941Smrg          *  UniformHandleui64{v}ARB if the sampler or image uniform being
1485b8e80941Smrg          *  updated has the "bound_sampler" or "bound_image" layout qualifier."
1486b8e80941Smrg          *
1487b8e80941Smrg          * From section 4.4.6 of the ARB_bindless_texture spec:
1488b8e80941Smrg          *
1489b8e80941Smrg          * "In the absence of these qualifiers, sampler and image uniforms are
1490b8e80941Smrg          *  considered "bound". Additionally, if GL_ARB_bindless_texture is
1491b8e80941Smrg          *  not enabled, these uniforms are considered "bound"."
1492b8e80941Smrg          */
1493b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1494b8e80941Smrg                     "glUniformHandleui64*ARB(non-bindless sampler/image uniform)");
1495b8e80941Smrg         return;
1496b8e80941Smrg      }
1497848b8605Smrg   }
1498848b8605Smrg
1499b8e80941Smrg   const unsigned components = uni->type->vector_elements;
1500b8e80941Smrg   const int size_mul = 2;
1501848b8605Smrg
1502b8e80941Smrg   if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
1503b8e80941Smrg      log_uniform(values, GLSL_TYPE_UINT64, components, 1, count,
1504b8e80941Smrg                  false, shProg, location, uni);
1505b8e80941Smrg   }
1506848b8605Smrg
1507b8e80941Smrg   /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
1508b8e80941Smrg    *
1509b8e80941Smrg    *     "When loading N elements starting at an arbitrary position k in a
1510b8e80941Smrg    *     uniform declared as an array, elements k through k + N - 1 in the
1511b8e80941Smrg    *     array will be replaced with the new values. Values for any array
1512b8e80941Smrg    *     element that exceeds the highest array element index used, as
1513b8e80941Smrg    *     reported by GetActiveUniform, will be ignored by the GL."
1514b8e80941Smrg    *
1515b8e80941Smrg    * Clamp 'count' to a valid value.  Note that for non-arrays a count > 1
1516b8e80941Smrg    * will have already generated an error.
1517848b8605Smrg    */
1518b8e80941Smrg   if (uni->array_elements != 0) {
1519b8e80941Smrg      count = MIN2(count, (int) (uni->array_elements - offset));
1520b8e80941Smrg   }
1521848b8605Smrg
1522b8e80941Smrg   _mesa_flush_vertices_for_uniforms(ctx, uni);
1523848b8605Smrg
1524b8e80941Smrg   /* Store the data in the "actual type" backing storage for the uniform.
1525848b8605Smrg    */
1526b8e80941Smrg   gl_constant_value *storage;
1527b8e80941Smrg   if (ctx->Const.PackedDriverUniformStorage) {
1528b8e80941Smrg      for (unsigned s = 0; s < uni->num_driver_storage; s++) {
1529b8e80941Smrg         storage = (gl_constant_value *)
1530b8e80941Smrg            uni->driver_storage[s].data + (size_mul * offset * components);
1531b8e80941Smrg         memcpy(storage, values,
1532b8e80941Smrg                sizeof(uni->storage[0]) * components * count * size_mul);
1533b8e80941Smrg      }
1534b8e80941Smrg   } else {
1535b8e80941Smrg      memcpy(&uni->storage[size_mul * components * offset], values,
1536b8e80941Smrg             sizeof(uni->storage[0]) * components * count * size_mul);
1537b8e80941Smrg
1538b8e80941Smrg      _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
1539848b8605Smrg   }
1540848b8605Smrg
1541b8e80941Smrg   if (uni->type->is_sampler()) {
1542b8e80941Smrg      /* Mark this bindless sampler as not bound to a texture unit because
1543b8e80941Smrg       * it refers to a texture handle.
1544b8e80941Smrg       */
1545b8e80941Smrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1546b8e80941Smrg         struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
1547848b8605Smrg
1548b8e80941Smrg         /* If the shader stage doesn't use the sampler uniform, skip this. */
1549b8e80941Smrg         if (!uni->opaque[i].active)
1550b8e80941Smrg            continue;
1551848b8605Smrg
1552b8e80941Smrg         for (int j = 0; j < count; j++) {
1553b8e80941Smrg            unsigned unit = uni->opaque[i].index + offset + j;
1554b8e80941Smrg            struct gl_bindless_sampler *sampler =
1555b8e80941Smrg               &sh->Program->sh.BindlessSamplers[unit];
1556848b8605Smrg
1557b8e80941Smrg            sampler->bound = false;
1558b8e80941Smrg         }
1559848b8605Smrg
1560b8e80941Smrg         update_bound_bindless_sampler_flag(sh->Program);
1561b8e80941Smrg      }
1562b8e80941Smrg   }
1563848b8605Smrg
1564b8e80941Smrg   if (uni->type->is_image()) {
1565b8e80941Smrg      /* Mark this bindless image as not bound to an image unit because it
1566b8e80941Smrg       * refers to a texture handle.
1567b8e80941Smrg       */
1568b8e80941Smrg      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1569b8e80941Smrg         struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
1570b8e80941Smrg
1571b8e80941Smrg         /* If the shader stage doesn't use the sampler uniform, skip this. */
1572b8e80941Smrg         if (!uni->opaque[i].active)
1573b8e80941Smrg            continue;
1574b8e80941Smrg
1575b8e80941Smrg         for (int j = 0; j < count; j++) {
1576b8e80941Smrg            unsigned unit = uni->opaque[i].index + offset + j;
1577b8e80941Smrg            struct gl_bindless_image *image =
1578b8e80941Smrg               &sh->Program->sh.BindlessImages[unit];
1579b8e80941Smrg
1580b8e80941Smrg            image->bound = false;
1581b8e80941Smrg         }
1582b8e80941Smrg
1583b8e80941Smrg         update_bound_bindless_image_flag(sh->Program);
1584848b8605Smrg      }
1585848b8605Smrg   }
1586b8e80941Smrg}
1587848b8605Smrg
1588b8e80941Smrgextern "C" bool
1589b8e80941Smrg_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
1590b8e80941Smrg				 char *errMsg, size_t errMsgLength)
1591b8e80941Smrg{
1592b8e80941Smrg   /* Shader does not have samplers. */
1593b8e80941Smrg   if (shProg->data->NumUniformStorage == 0)
1594b8e80941Smrg      return true;
1595b8e80941Smrg
1596b8e80941Smrg   if (!shProg->SamplersValidated) {
1597b8e80941Smrg      _mesa_snprintf(errMsg, errMsgLength,
1598b8e80941Smrg                     "active samplers with a different type "
1599b8e80941Smrg                     "refer to the same texture image unit");
1600b8e80941Smrg      return false;
1601b8e80941Smrg   }
1602848b8605Smrg   return true;
1603848b8605Smrg}
1604848b8605Smrg
1605848b8605Smrgextern "C" bool
1606848b8605Smrg_mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline)
1607848b8605Smrg{
1608848b8605Smrg   /* Section 2.11.11 (Shader Execution), subheading "Validation," of the
1609848b8605Smrg    * OpenGL 4.1 spec says:
1610848b8605Smrg    *
1611848b8605Smrg    *     "[INVALID_OPERATION] is generated by any command that transfers
1612848b8605Smrg    *     vertices to the GL if:
1613848b8605Smrg    *
1614848b8605Smrg    *         ...
1615848b8605Smrg    *
1616848b8605Smrg    *         - Any two active samplers in the current program object are of
1617848b8605Smrg    *           different types, but refer to the same texture image unit.
1618848b8605Smrg    *
1619848b8605Smrg    *         - The number of active samplers in the program exceeds the
1620848b8605Smrg    *           maximum number of texture image units allowed."
1621848b8605Smrg    */
1622b8e80941Smrg
1623b8e80941Smrg   GLbitfield mask;
1624b8e80941Smrg   GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
1625848b8605Smrg   unsigned active_samplers = 0;
1626b8e80941Smrg   const struct gl_program **prog =
1627b8e80941Smrg      (const struct gl_program **) pipeline->CurrentProgram;
1628b8e80941Smrg
1629848b8605Smrg
1630b8e80941Smrg   memset(TexturesUsed, 0, sizeof(TexturesUsed));
1631848b8605Smrg
1632848b8605Smrg   for (unsigned idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
1633b8e80941Smrg      if (!prog[idx])
1634848b8605Smrg         continue;
1635848b8605Smrg
1636b8e80941Smrg      mask = prog[idx]->SamplersUsed;
1637b8e80941Smrg      while (mask) {
1638b8e80941Smrg         const int s = u_bit_scan(&mask);
1639b8e80941Smrg         GLuint unit = prog[idx]->SamplerUnits[s];
1640b8e80941Smrg         GLuint tgt = prog[idx]->sh.SamplerTargets[s];
1641848b8605Smrg
1642b8e80941Smrg         /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a
1643b8e80941Smrg          * great job of eliminating unused uniforms currently so for now
1644b8e80941Smrg          * don't throw an error if two sampler types both point to 0.
1645b8e80941Smrg          */
1646b8e80941Smrg         if (unit == 0)
1647848b8605Smrg            continue;
1648848b8605Smrg
1649b8e80941Smrg         if (TexturesUsed[unit] & ~(1 << tgt)) {
1650b8e80941Smrg            pipeline->InfoLog =
1651b8e80941Smrg               ralloc_asprintf(pipeline,
1652b8e80941Smrg                     "Program %d: "
1653b8e80941Smrg                     "Texture unit %d is accessed with 2 different types",
1654b8e80941Smrg                     prog[idx]->Id, unit);
1655b8e80941Smrg            return false;
1656848b8605Smrg         }
1657b8e80941Smrg
1658b8e80941Smrg         TexturesUsed[unit] |= (1 << tgt);
1659848b8605Smrg      }
1660b8e80941Smrg
1661b8e80941Smrg      active_samplers += prog[idx]->info.num_textures;
1662848b8605Smrg   }
1663848b8605Smrg
1664848b8605Smrg   if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {
1665848b8605Smrg      pipeline->InfoLog =
1666848b8605Smrg         ralloc_asprintf(pipeline,
1667848b8605Smrg                         "the number of active samplers %d exceed the "
1668848b8605Smrg                         "maximum %d",
1669848b8605Smrg                         active_samplers, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
1670848b8605Smrg      return false;
1671848b8605Smrg   }
1672848b8605Smrg
1673848b8605Smrg   return true;
1674848b8605Smrg}
1675