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