mesa: Add log_uniform and log_program_parameters to dump data
[mesa.git] / src / mesa / main / uniform_query.cpp
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 #include "main/core.h"
26 #include "main/context.h"
27 #include "ir.h"
28 #include "ir_uniform.h"
29 #include "../glsl/program.h"
30 #include "../glsl/ir_uniform.h"
31
32 extern "C" {
33 #include "main/image.h"
34 #include "main/shaderapi.h"
35 #include "main/shaderobj.h"
36 #include "uniforms.h"
37 }
38
39 extern "C" void GLAPIENTRY
40 _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
41 GLsizei maxLength, GLsizei *length, GLint *size,
42 GLenum *type, GLcharARB *nameOut)
43 {
44 GET_CURRENT_CONTEXT(ctx);
45 struct gl_shader_program *shProg =
46 _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
47 const struct gl_program_parameter *param;
48
49 if (!shProg)
50 return;
51
52 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
53 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
54 return;
55 }
56
57 param = get_uniform_parameter(shProg, index);
58 if (!param)
59 return;
60
61 const struct gl_uniform *const uni = &shProg->Uniforms->Uniforms[index];
62
63 if (nameOut) {
64 _mesa_copy_string(nameOut, maxLength, length, param->Name);
65 }
66
67 if (size) {
68 GLint typeSize = _mesa_sizeof_glsl_type(uni->Type->gl_type);
69 if ((GLint) param->Size > typeSize) {
70 /* This is an array.
71 * Array elements are placed on vector[4] boundaries so they're
72 * a multiple of four floats. We round typeSize up to next multiple
73 * of four to get the right size below.
74 */
75 typeSize = (typeSize + 3) & ~3;
76 }
77 /* Note that the returned size is in units of the <type>, not bytes */
78 *size = param->Size / typeSize;
79 }
80
81 if (type) {
82 *type = uni->Type->gl_type;
83 }
84 }
85
86 static GLenum
87 base_uniform_type(GLenum type)
88 {
89 switch (type) {
90 case GL_BOOL:
91 case GL_BOOL_VEC2:
92 case GL_BOOL_VEC3:
93 case GL_BOOL_VEC4:
94 return GL_BOOL;
95 case GL_FLOAT:
96 case GL_FLOAT_VEC2:
97 case GL_FLOAT_VEC3:
98 case GL_FLOAT_VEC4:
99 case GL_FLOAT_MAT2:
100 case GL_FLOAT_MAT2x3:
101 case GL_FLOAT_MAT2x4:
102 case GL_FLOAT_MAT3x2:
103 case GL_FLOAT_MAT3:
104 case GL_FLOAT_MAT3x4:
105 case GL_FLOAT_MAT4x2:
106 case GL_FLOAT_MAT4x3:
107 case GL_FLOAT_MAT4:
108 return GL_FLOAT;
109 case GL_UNSIGNED_INT:
110 case GL_UNSIGNED_INT_VEC2:
111 case GL_UNSIGNED_INT_VEC3:
112 case GL_UNSIGNED_INT_VEC4:
113 return GL_UNSIGNED_INT;
114 case GL_INT:
115 case GL_INT_VEC2:
116 case GL_INT_VEC3:
117 case GL_INT_VEC4:
118 return GL_INT;
119 default:
120 _mesa_problem(NULL, "Invalid type in base_uniform_type()");
121 return GL_FLOAT;
122 }
123 }
124
125 static GLboolean
126 is_boolean_type(GLenum type)
127 {
128 switch (type) {
129 case GL_BOOL:
130 case GL_BOOL_VEC2:
131 case GL_BOOL_VEC3:
132 case GL_BOOL_VEC4:
133 return GL_TRUE;
134 default:
135 return GL_FALSE;
136 }
137 }
138
139 static GLboolean
140 is_sampler_type(GLenum type)
141 {
142 switch (type) {
143 case GL_SAMPLER_1D:
144 case GL_INT_SAMPLER_1D:
145 case GL_UNSIGNED_INT_SAMPLER_1D:
146 case GL_SAMPLER_2D:
147 case GL_INT_SAMPLER_2D:
148 case GL_UNSIGNED_INT_SAMPLER_2D:
149 case GL_SAMPLER_3D:
150 case GL_INT_SAMPLER_3D:
151 case GL_UNSIGNED_INT_SAMPLER_3D:
152 case GL_SAMPLER_CUBE:
153 case GL_INT_SAMPLER_CUBE:
154 case GL_UNSIGNED_INT_SAMPLER_CUBE:
155 case GL_SAMPLER_1D_SHADOW:
156 case GL_SAMPLER_2D_SHADOW:
157 case GL_SAMPLER_CUBE_SHADOW:
158 case GL_SAMPLER_2D_RECT_ARB:
159 case GL_INT_SAMPLER_2D_RECT:
160 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
161 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
162 case GL_SAMPLER_1D_ARRAY_EXT:
163 case GL_INT_SAMPLER_1D_ARRAY:
164 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
165 case GL_SAMPLER_2D_ARRAY_EXT:
166 case GL_INT_SAMPLER_2D_ARRAY:
167 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
168 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
169 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
170 case GL_SAMPLER_CUBE_MAP_ARRAY:
171 case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
172 case GL_SAMPLER_BUFFER:
173 case GL_INT_SAMPLER_BUFFER:
174 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
175 case GL_SAMPLER_2D_MULTISAMPLE:
176 case GL_INT_SAMPLER_2D_MULTISAMPLE:
177 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
178 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
179 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
180 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
181 case GL_SAMPLER_EXTERNAL_OES:
182 return GL_TRUE;
183 default:
184 return GL_FALSE;
185 }
186 }
187
188 /**
189 * Given a uniform index, return the vertex/geometry/fragment program
190 * that has that parameter, plus the position of the parameter in the
191 * parameter/constant buffer.
192 * \param shProg the shader program
193 * \param index the uniform index in [0, NumUniforms-1]
194 * \param progOut returns containing program
195 * \param posOut returns position of the uniform in the param/const buffer
196 * \return GL_TRUE for success, GL_FALSE for invalid index
197 */
198 static GLboolean
199 find_uniform_parameter_pos(struct gl_shader_program *shProg, GLint index,
200 struct gl_program **progOut, GLint *posOut)
201 {
202 struct gl_program *prog = NULL;
203 GLint pos;
204
205 if (!shProg->Uniforms ||
206 index < 0 ||
207 index >= (GLint) shProg->Uniforms->NumUniforms) {
208 return GL_FALSE;
209 }
210
211 pos = shProg->Uniforms->Uniforms[index].VertPos;
212 if (pos >= 0) {
213 prog = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
214 }
215 else {
216 pos = shProg->Uniforms->Uniforms[index].FragPos;
217 if (pos >= 0) {
218 prog = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
219 }
220 else {
221 pos = shProg->Uniforms->Uniforms[index].GeomPos;
222 if (pos >= 0) {
223 prog = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
224 }
225 }
226 }
227
228 if (!prog || pos < 0)
229 return GL_FALSE; /* should really never happen */
230
231 *progOut = prog;
232 *posOut = pos;
233
234 return GL_TRUE;
235 }
236
237 /**
238 * Return pointer to a gl_program_parameter which corresponds to a uniform.
239 * \param shProg the shader program
240 * \param index the uniform index in [0, NumUniforms-1]
241 * \return gl_program_parameter point or NULL if index is invalid
242 */
243 const struct gl_program_parameter *
244 get_uniform_parameter(struct gl_shader_program *shProg, GLint index)
245 {
246 struct gl_program *prog;
247 GLint progPos;
248
249 if (find_uniform_parameter_pos(shProg, index, &prog, &progPos))
250 return &prog->Parameters->Parameters[progPos];
251 else
252 return NULL;
253 }
254
255 static unsigned
256 get_vector_elements(GLenum type)
257 {
258 switch (type) {
259 case GL_FLOAT:
260 case GL_INT:
261 case GL_BOOL:
262 case GL_UNSIGNED_INT:
263 default: /* Catch all the various sampler types. */
264 return 1;
265
266 case GL_FLOAT_VEC2:
267 case GL_INT_VEC2:
268 case GL_BOOL_VEC2:
269 case GL_UNSIGNED_INT_VEC2:
270 return 2;
271
272 case GL_FLOAT_VEC3:
273 case GL_INT_VEC3:
274 case GL_BOOL_VEC3:
275 case GL_UNSIGNED_INT_VEC3:
276 return 3;
277
278 case GL_FLOAT_VEC4:
279 case GL_INT_VEC4:
280 case GL_BOOL_VEC4:
281 case GL_UNSIGNED_INT_VEC4:
282 return 4;
283 }
284 }
285
286 static void
287 get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
288 {
289 switch (type) {
290 case GL_FLOAT_MAT2:
291 *rows = *cols = 2;
292 break;
293 case GL_FLOAT_MAT2x3:
294 *rows = 3;
295 *cols = 2;
296 break;
297 case GL_FLOAT_MAT2x4:
298 *rows = 4;
299 *cols = 2;
300 break;
301 case GL_FLOAT_MAT3:
302 *rows = 3;
303 *cols = 3;
304 break;
305 case GL_FLOAT_MAT3x2:
306 *rows = 2;
307 *cols = 3;
308 break;
309 case GL_FLOAT_MAT3x4:
310 *rows = 4;
311 *cols = 3;
312 break;
313 case GL_FLOAT_MAT4:
314 *rows = 4;
315 *cols = 4;
316 break;
317 case GL_FLOAT_MAT4x2:
318 *rows = 2;
319 *cols = 4;
320 break;
321 case GL_FLOAT_MAT4x3:
322 *rows = 3;
323 *cols = 4;
324 break;
325 default:
326 *rows = *cols = 0;
327 }
328 }
329
330 /**
331 * Determine the number of rows and columns occupied by a uniform
332 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
333 * the number of rows = 1 and cols = number of elements in the vector.
334 */
335 static void
336 get_uniform_rows_cols(const struct gl_program_parameter *p,
337 GLint *rows, GLint *cols)
338 {
339 get_matrix_dims(p->DataType, rows, cols);
340 if (*rows == 0 && *cols == 0) {
341 /* not a matrix type, probably a float or vector */
342 *rows = 1;
343 *cols = get_vector_elements(p->DataType);
344 }
345 }
346
347 static bool
348 validate_uniform_parameters(struct gl_context *ctx,
349 struct gl_shader_program *shProg,
350 GLint location, GLsizei count,
351 unsigned *loc,
352 unsigned *array_index,
353 const char *caller,
354 bool negative_one_is_not_valid)
355 {
356 if (!shProg || !shProg->LinkStatus) {
357 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
358 return false;
359 }
360
361 if (location == -1) {
362 /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
363 * spec says:
364 *
365 * "The error INVALID_OPERATION is generated if program has not been
366 * linked successfully, or if location is not a valid location for
367 * program."
368 *
369 * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
370 * says:
371 *
372 * "If the value of location is -1, the Uniform* commands will
373 * silently ignore the data passed in, and the current uniform
374 * values will not be changed."
375 *
376 * Allowing -1 for the location parameter of glUniform allows
377 * applications to avoid error paths in the case that, for example, some
378 * uniform variable is removed by the compiler / linker after
379 * optimization. In this case, the new value of the uniform is dropped
380 * on the floor. For the case of glGetUniform, there is nothing
381 * sensible to do for a location of -1.
382 *
383 * The negative_one_is_not_valid flag selects between the two behaviors.
384 */
385 if (negative_one_is_not_valid) {
386 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
387 caller, location);
388 }
389
390 return false;
391 }
392
393 /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
394 *
395 * "If a negative number is provided where an argument of type sizei or
396 * sizeiptr is specified, the error INVALID_VALUE is generated."
397 */
398 if (count < 0) {
399 _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller);
400 return false;
401 }
402
403 /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
404 *
405 * "If any of the following conditions occur, an INVALID_OPERATION
406 * error is generated by the Uniform* commands, and no uniform values
407 * are changed:
408 *
409 * ...
410 *
411 * - if no variable with a location of location exists in the
412 * program object currently in use and location is not -1,
413 */
414 if (location < -1) {
415 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
416 caller, location);
417 return false;
418 }
419
420 _mesa_uniform_split_location_offset(location, loc, array_index);
421
422 if (*loc >= shProg->Uniforms->NumUniforms) {
423 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
424 caller, location);
425 return false;
426 }
427
428 return true;
429 }
430
431 /**
432 * Called via glGetUniform[fiui]v() to get the current value of a uniform.
433 */
434 extern "C" void
435 _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
436 GLsizei bufSize, GLenum returnType, GLvoid *paramsOut)
437 {
438 struct gl_shader_program *shProg =
439 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
440 struct gl_program *prog;
441 GLint paramPos;
442 unsigned loc, offset;
443
444 if (!validate_uniform_parameters(ctx, shProg, location, 1,
445 &loc, &offset, "glGetUniform", true))
446 return;
447
448 if (!find_uniform_parameter_pos(shProg, loc, &prog, &paramPos)) {
449 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
450 }
451 else {
452 const struct gl_program_parameter *p =
453 &prog->Parameters->Parameters[paramPos];
454 gl_constant_value (*values)[4];
455 GLint rows, cols, i, j, k;
456 GLsizei numBytes;
457 GLenum storage_type;
458
459 values = prog->Parameters->ParameterValues + paramPos + offset;
460
461 get_uniform_rows_cols(p, &rows, &cols);
462
463 numBytes = rows * cols * _mesa_sizeof_type(returnType);
464 if (bufSize < numBytes) {
465 _mesa_error( ctx, GL_INVALID_OPERATION,
466 "glGetnUniformfvARB(out of bounds: bufSize is %d,"
467 " but %d bytes are required)", bufSize, numBytes );
468 return;
469 }
470
471 if (ctx->Const.NativeIntegers) {
472 storage_type = base_uniform_type(p->DataType);
473 } else {
474 storage_type = GL_FLOAT;
475 }
476
477 k = 0;
478 for (i = 0; i < rows; i++) {
479 for (j = 0; j < cols; j++ ) {
480 void *out = (char *)paramsOut + 4 * k;
481
482 switch (returnType) {
483 case GL_FLOAT:
484 switch (storage_type) {
485 case GL_FLOAT:
486 *(float *)out = values[i][j].f;
487 break;
488 case GL_INT:
489 case GL_BOOL: /* boolean is just an integer 1 or 0. */
490 *(float *)out = values[i][j].i;
491 break;
492 case GL_UNSIGNED_INT:
493 *(float *)out = values[i][j].u;
494 break;
495 }
496 break;
497
498 case GL_INT:
499 case GL_UNSIGNED_INT:
500 switch (storage_type) {
501 case GL_FLOAT:
502 /* While the GL 3.2 core spec doesn't explicitly
503 * state how conversion of float uniforms to integer
504 * values works, in section 6.2 "State Tables" on
505 * page 267 it says:
506 *
507 * "Unless otherwise specified, when floating
508 * point state is returned as integer values or
509 * integer state is returned as floating-point
510 * values it is converted in the fashion
511 * described in section 6.1.2"
512 *
513 * That section, on page 248, says:
514 *
515 * "If GetIntegerv or GetInteger64v are called,
516 * a floating-point value is rounded to the
517 * nearest integer..."
518 */
519 *(int *)out = IROUND(values[i][j].f);
520 break;
521
522 case GL_INT:
523 case GL_UNSIGNED_INT:
524 case GL_BOOL:
525 /* type conversions for these to int/uint are just
526 * copying the data.
527 */
528 *(int *)out = values[i][j].i;
529 break;
530 break;
531 }
532 break;
533 }
534
535 k++;
536 }
537 }
538 }
539 }
540
541 static void
542 log_uniform(const void *values, enum glsl_base_type basicType,
543 unsigned rows, unsigned cols, unsigned count,
544 bool transpose,
545 const struct gl_shader_program *shProg,
546 GLint location,
547 const struct gl_uniform_storage *uni)
548 {
549
550 const union gl_constant_value *v = (const union gl_constant_value *) values;
551 const unsigned elems = rows * cols * count;
552 const char *const extra = (cols == 1) ? "uniform" : "uniform matrix";
553
554 printf("Mesa: set program %u %s \"%s\" (loc %d, type \"%s\", "
555 "transpose = %s) to: ",
556 shProg->Name, extra, uni->name, location, uni->type->name,
557 transpose ? "true" : "false");
558 for (unsigned i = 0; i < elems; i++) {
559 if (i != 0 && ((i % rows) == 0))
560 printf(", ");
561
562 switch (basicType) {
563 case GLSL_TYPE_UINT:
564 printf("%u ", v[i].u);
565 break;
566 case GLSL_TYPE_INT:
567 printf("%d ", v[i].i);
568 break;
569 case GLSL_TYPE_FLOAT:
570 printf("%g ", v[i].f);
571 break;
572 default:
573 assert(!"Should not get here.");
574 break;
575 }
576 }
577 printf("\n");
578 fflush(stdout);
579 }
580
581 #if 0
582 static void
583 log_program_parameters(const struct gl_shader_program *shProg)
584 {
585 static const char *stages[] = {
586 "vertex", "fragment", "geometry"
587 };
588
589 assert(Elements(stages) == MESA_SHADER_TYPES);
590
591 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
592 if (shProg->_LinkedShaders[i] == NULL)
593 continue;
594
595 const struct gl_program *const prog = shProg->_LinkedShaders[i]->Program;
596
597 printf("Program %d %s shader parameters:\n",
598 shProg->Name, stages[i]);
599 for (unsigned j = 0; j < prog->Parameters->NumParameters; j++) {
600 printf("%s: %p %f %f %f %f\n",
601 prog->Parameters->Parameters[j].Name,
602 prog->Parameters->ParameterValues[j],
603 prog->Parameters->ParameterValues[j][0].f,
604 prog->Parameters->ParameterValues[j][1].f,
605 prog->Parameters->ParameterValues[j][2].f,
606 prog->Parameters->ParameterValues[j][3].f);
607 }
608 }
609 fflush(stdout);
610 }
611 #endif
612
613 /**
614 * Check if the type given by userType is allowed to set a uniform of the
615 * target type. Generally, equivalence is required, but setting Boolean
616 * uniforms can be done with glUniformiv or glUniformfv.
617 */
618 static GLboolean
619 compatible_types(GLenum userType, GLenum targetType)
620 {
621 if (userType == targetType)
622 return GL_TRUE;
623
624 if (targetType == GL_BOOL && (userType == GL_FLOAT ||
625 userType == GL_UNSIGNED_INT ||
626 userType == GL_INT))
627 return GL_TRUE;
628
629 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
630 userType == GL_UNSIGNED_INT_VEC2 ||
631 userType == GL_INT_VEC2))
632 return GL_TRUE;
633
634 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
635 userType == GL_UNSIGNED_INT_VEC3 ||
636 userType == GL_INT_VEC3))
637 return GL_TRUE;
638
639 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
640 userType == GL_UNSIGNED_INT_VEC4 ||
641 userType == GL_INT_VEC4))
642 return GL_TRUE;
643
644 if (is_sampler_type(targetType) && userType == GL_INT)
645 return GL_TRUE;
646
647 return GL_FALSE;
648 }
649
650 /**
651 * Set the value of a program's uniform variable.
652 * \param program the program whose uniform to update
653 * \param index the index of the program parameter for the uniform
654 * \param offset additional parameter slot offset (for arrays)
655 * \param type the incoming datatype of 'values'
656 * \param count the number of uniforms to set
657 * \param elems number of elements per uniform (1, 2, 3 or 4)
658 * \param values the new values, of datatype 'type'
659 */
660 static void
661 set_program_uniform(struct gl_context *ctx, struct gl_program *program,
662 GLint index, GLint offset,
663 GLenum type, GLsizei count, GLint elems,
664 const void *values)
665 {
666 const struct gl_program_parameter *param =
667 &program->Parameters->Parameters[index];
668
669 assert(offset >= 0);
670 assert(elems >= 1);
671 assert(elems <= 4);
672
673 if (!compatible_types(type, param->DataType)) {
674 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
675 return;
676 }
677
678 if (index + offset > (GLint) program->Parameters->Size) {
679 /* out of bounds! */
680 return;
681 }
682
683 if (param->Type == PROGRAM_SAMPLER) {
684 /* This controls which texture unit which is used by a sampler */
685 GLboolean changed = GL_FALSE;
686 GLint i;
687
688 /* this should have been caught by the compatible_types() check */
689 ASSERT(type == GL_INT);
690
691 /* loop over number of samplers to change */
692 for (i = 0; i < count; i++) {
693 GLuint sampler = (GLuint)
694 program->Parameters->ParameterValues[index+offset + i][0].f;
695 GLuint texUnit = ((GLuint *) values)[i];
696
697 /* check that the sampler (tex unit index) is legal */
698 if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
699 _mesa_error(ctx, GL_INVALID_VALUE,
700 "glUniform1(invalid sampler/tex unit index for '%s')",
701 param->Name);
702 return;
703 }
704
705 /* This maps a sampler to a texture unit: */
706 if (sampler < MAX_SAMPLERS) {
707 #if 0
708 printf("Set program %p sampler %d '%s' to unit %u\n",
709 program, sampler, param->Name, texUnit);
710 #endif
711 if (program->SamplerUnits[sampler] != texUnit) {
712 program->SamplerUnits[sampler] = texUnit;
713 changed = GL_TRUE;
714 }
715 }
716 }
717
718 if (changed) {
719 /* When a sampler's value changes it usually requires rewriting
720 * a GPU program's TEX instructions since there may not be a
721 * sampler->texture lookup table. We signal this with the
722 * ProgramStringNotify() callback.
723 */
724 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
725 _mesa_update_shader_textures_used(program);
726 /* Do we need to care about the return value here?
727 * This should not be the first time the driver was notified of
728 * this program.
729 */
730 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
731 }
732 }
733 else {
734 /* ordinary uniform variable */
735 const GLboolean isUniformBool = is_boolean_type(param->DataType);
736 const GLenum basicType = base_uniform_type(type);
737 const GLint slots = (param->Size + 3) / 4;
738 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
739 GLsizei k, i;
740
741 if ((GLint) param->Size > typeSize) {
742 /* an array */
743 /* we'll ignore extra data below */
744 }
745 else {
746 /* non-array: count must be at most one; count == 0 is handled
747 * by the loop below
748 */
749 if (count > 1) {
750 _mesa_error(ctx, GL_INVALID_OPERATION,
751 "glUniform(uniform '%s' is not an array)",
752 param->Name);
753 return;
754 }
755 }
756
757 /* loop over number of array elements */
758 for (k = 0; k < count; k++) {
759 gl_constant_value *uniformVal;
760
761 if (offset + k >= slots) {
762 /* Extra array data is ignored */
763 break;
764 }
765
766 /* uniformVal (the destination) is always gl_constant_value[4] */
767 uniformVal = program->Parameters->ParameterValues[index + offset + k];
768
769 if (basicType == GL_INT) {
770 const GLint *iValues = ((const GLint *) values) + k * elems;
771 for (i = 0; i < elems; i++) {
772 if (!ctx->Const.NativeIntegers)
773 uniformVal[i].f = (GLfloat) iValues[i];
774 else
775 uniformVal[i].i = iValues[i];
776 }
777 }
778 else if (basicType == GL_UNSIGNED_INT) {
779 const GLuint *iValues = ((const GLuint *) values) + k * elems;
780 for (i = 0; i < elems; i++) {
781 if (!ctx->Const.NativeIntegers)
782 uniformVal[i].f = (GLfloat)(GLuint) iValues[i];
783 else
784 uniformVal[i].u = iValues[i];
785 }
786 }
787 else {
788 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
789 assert(basicType == GL_FLOAT);
790 for (i = 0; i < elems; i++) {
791 uniformVal[i].f = fValues[i];
792 }
793 }
794
795 /* if the uniform is bool-valued, convert to 1 or 0 */
796 if (isUniformBool) {
797 for (i = 0; i < elems; i++) {
798 if (basicType == GL_FLOAT)
799 uniformVal[i].b = uniformVal[i].f != 0.0f ? 1 : 0;
800 else
801 uniformVal[i].b = uniformVal[i].u ? 1 : 0;
802
803 if (ctx->Const.NativeIntegers)
804 uniformVal[i].u =
805 uniformVal[i].b ? ctx->Const.UniformBooleanTrue : 0;
806 else
807 uniformVal[i].f = uniformVal[i].b ? 1.0f : 0.0f;
808 }
809 }
810 }
811 }
812 }
813
814 /**
815 * Propagate some values from uniform backing storage to driver storage
816 *
817 * Values propagated from uniform backing storage to driver storage
818 * have all format / type conversions previously requested by the
819 * driver applied. This function is most often called by the
820 * implementations of \c glUniform1f, etc. and \c glUniformMatrix2f,
821 * etc.
822 *
823 * \param uni Uniform whose data is to be propagated to driver storage
824 * \param array_index If \c uni is an array, this is the element of
825 * the array to be propagated.
826 * \param count Number of array elements to propagate.
827 */
828 extern "C" void
829 _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni,
830 unsigned array_index,
831 unsigned count)
832 {
833 unsigned i;
834
835 /* vector_elements and matrix_columns can be 0 for samplers.
836 */
837 const unsigned components = MAX2(1, uni->type->vector_elements);
838 const unsigned vectors = MAX2(1, uni->type->matrix_columns);
839
840 /* Store the data in the driver's requested type in the driver's storage
841 * areas.
842 */
843 unsigned src_vector_byte_stride = components * 4;
844
845 for (i = 0; i < uni->num_driver_storage; i++) {
846 struct gl_uniform_driver_storage *const store = &uni->driver_storage[i];
847 uint8_t *dst = (uint8_t *) store->data;
848 const unsigned extra_stride =
849 store->element_stride - (vectors * store->vector_stride);
850 const uint8_t *src =
851 (uint8_t *) (&uni->storage[array_index * (components * vectors)].i);
852
853 #if 0
854 printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
855 "extra_stride=%u\n",
856 __func__, dst, array_index, components,
857 vectors, count, store->vector_stride, extra_stride);
858 #endif
859
860 dst += array_index * store->element_stride;
861
862 switch (store->format) {
863 case uniform_native:
864 case uniform_bool_int_0_1: {
865 unsigned j;
866 unsigned v;
867
868 for (j = 0; j < count; j++) {
869 for (v = 0; v < vectors; v++) {
870 memcpy(dst, src, src_vector_byte_stride);
871 src += src_vector_byte_stride;
872 dst += store->vector_stride;
873 }
874
875 dst += extra_stride;
876 }
877 break;
878 }
879
880 case uniform_int_float:
881 case uniform_bool_float: {
882 const int *isrc = (const int *) src;
883 unsigned j;
884 unsigned v;
885 unsigned c;
886
887 for (j = 0; j < count; j++) {
888 for (v = 0; v < vectors; v++) {
889 for (c = 0; c < components; c++) {
890 ((float *) dst)[c] = (float) *isrc;
891 isrc++;
892 }
893
894 dst += store->vector_stride;
895 }
896
897 dst += extra_stride;
898 }
899 break;
900 }
901
902 case uniform_bool_int_0_not0: {
903 const int *isrc = (const int *) src;
904 unsigned j;
905 unsigned v;
906 unsigned c;
907
908 for (j = 0; j < count; j++) {
909 for (v = 0; v < vectors; v++) {
910 for (c = 0; c < components; c++) {
911 ((int *) dst)[c] = *isrc == 0 ? 0 : ~0;
912 isrc++;
913 }
914
915 dst += store->vector_stride;
916 }
917
918 dst += extra_stride;
919 }
920 break;
921 }
922
923 default:
924 assert(!"Should not get here.");
925 break;
926 }
927 }
928 }
929
930 /**
931 * Called via glUniform*() functions.
932 */
933 extern "C" void
934 _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
935 GLint location, GLsizei count,
936 const GLvoid *values, GLenum type)
937 {
938 struct gl_uniform *uniform;
939 GLint elems;
940 unsigned loc, offset;
941
942 ASSERT_OUTSIDE_BEGIN_END(ctx);
943
944 if (!validate_uniform_parameters(ctx, shProg, location, count,
945 &loc, &offset, "glUniform", false))
946 return;
947
948 elems = _mesa_sizeof_glsl_type(type);
949
950 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
951
952 uniform = &shProg->Uniforms->Uniforms[loc];
953
954 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
955 const GLenum basicType = base_uniform_type(type);
956 GLint i;
957 printf("Mesa: set program %u uniform %s (loc %d) to: ",
958 shProg->Name, uniform->Name, location);
959 if (basicType == GL_INT) {
960 const GLint *v = (const GLint *) values;
961 for (i = 0; i < count * elems; i++) {
962 printf("%d ", v[i]);
963 }
964 }
965 else if (basicType == GL_UNSIGNED_INT) {
966 const GLuint *v = (const GLuint *) values;
967 for (i = 0; i < count * elems; i++) {
968 printf("%u ", v[i]);
969 }
970 }
971 else {
972 const GLfloat *v = (const GLfloat *) values;
973 assert(basicType == GL_FLOAT);
974 for (i = 0; i < count * elems; i++) {
975 printf("%g ", v[i]);
976 }
977 }
978 printf("\n");
979 }
980
981 /* A uniform var may be used by both a vertex shader and a fragment
982 * shader. We may need to update one or both shader's uniform here:
983 */
984 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX]) {
985 /* convert uniform location to program parameter index */
986 GLint index = uniform->VertPos;
987 if (index >= 0) {
988 set_program_uniform(ctx,
989 shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program,
990 index, offset, type, count, elems, values);
991 }
992 }
993
994 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
995 /* convert uniform location to program parameter index */
996 GLint index = uniform->FragPos;
997 if (index >= 0) {
998 set_program_uniform(ctx,
999 shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program,
1000 index, offset, type, count, elems, values);
1001 }
1002 }
1003
1004 if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) {
1005 /* convert uniform location to program parameter index */
1006 GLint index = uniform->GeomPos;
1007 if (index >= 0) {
1008 set_program_uniform(ctx,
1009 shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program,
1010 index, offset, type, count, elems, values);
1011 }
1012 }
1013
1014 uniform->Initialized = GL_TRUE;
1015 }
1016
1017 /**
1018 * Set a matrix-valued program parameter.
1019 */
1020 static void
1021 set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
1022 GLuint index, GLuint offset,
1023 GLuint count, GLuint rows, GLuint cols,
1024 GLboolean transpose, const GLfloat *values)
1025 {
1026 GLuint mat, row, col;
1027 GLuint src = 0;
1028 const struct gl_program_parameter *param =
1029 &program->Parameters->Parameters[index];
1030 const GLuint slots = (param->Size + 3) / 4;
1031 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
1032 GLint nr, nc;
1033
1034 /* check that the number of rows, columns is correct */
1035 get_matrix_dims(param->DataType, &nr, &nc);
1036 if (rows != nr || cols != nc) {
1037 _mesa_error(ctx, GL_INVALID_OPERATION,
1038 "glUniformMatrix(matrix size mismatch)");
1039 return;
1040 }
1041
1042 if ((GLint) param->Size <= typeSize) {
1043 /* non-array: count must be at most one; count == 0 is handled
1044 * by the loop below
1045 */
1046 if (count > 1) {
1047 _mesa_error(ctx, GL_INVALID_OPERATION,
1048 "glUniformMatrix(uniform is not an array)");
1049 return;
1050 }
1051 }
1052
1053 /*
1054 * Note: the _columns_ of a matrix are stored in program registers, not
1055 * the rows. So, the loops below look a little funny.
1056 * XXX could optimize this a bit...
1057 */
1058
1059 /* loop over matrices */
1060 for (mat = 0; mat < count; mat++) {
1061
1062 /* each matrix: */
1063 for (col = 0; col < cols; col++) {
1064 GLfloat *v;
1065 if (offset >= slots) {
1066 /* Ignore writes beyond the end of (the used part of) an array */
1067 return;
1068 }
1069 v = (GLfloat *) program->Parameters->ParameterValues[index + offset];
1070 for (row = 0; row < rows; row++) {
1071 if (transpose) {
1072 v[row] = values[src + row * cols + col];
1073 }
1074 else {
1075 v[row] = values[src + col * rows + row];
1076 }
1077 }
1078
1079 offset++;
1080 }
1081
1082 src += rows * cols; /* next matrix */
1083 }
1084 }
1085
1086 /**
1087 * Called by glUniformMatrix*() functions.
1088 * Note: cols=2, rows=4 ==> array[2] of vec4
1089 */
1090 extern "C" void
1091 _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
1092 GLint cols, GLint rows,
1093 GLint location, GLsizei count,
1094 GLboolean transpose, const GLfloat *values)
1095 {
1096 struct gl_uniform *uniform;
1097 unsigned loc, offset;
1098
1099 ASSERT_OUTSIDE_BEGIN_END(ctx);
1100
1101 if (!validate_uniform_parameters(ctx, shProg, location, count,
1102 &loc, &offset, "glUniformMatrix", false))
1103 return;
1104
1105 if (values == NULL) {
1106 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1107 return;
1108 }
1109
1110 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1111
1112 uniform = &shProg->Uniforms->Uniforms[loc];
1113
1114 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX]) {
1115 /* convert uniform location to program parameter index */
1116 GLint index = uniform->VertPos;
1117 if (index >= 0) {
1118 set_program_uniform_matrix(ctx,
1119 shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program,
1120 index, offset,
1121 count, rows, cols, transpose, values);
1122 }
1123 }
1124
1125 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
1126 /* convert uniform location to program parameter index */
1127 GLint index = uniform->FragPos;
1128 if (index >= 0) {
1129 set_program_uniform_matrix(ctx,
1130 shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program,
1131 index, offset,
1132 count, rows, cols, transpose, values);
1133 }
1134 }
1135
1136 if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) {
1137 /* convert uniform location to program parameter index */
1138 GLint index = uniform->GeomPos;
1139 if (index >= 0) {
1140 set_program_uniform_matrix(ctx,
1141 shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program,
1142 index, offset,
1143 count, rows, cols, transpose, values);
1144 }
1145 }
1146
1147 uniform->Initialized = GL_TRUE;
1148 }
1149
1150 /**
1151 * Called via glGetUniformLocation().
1152 *
1153 * The return value will encode two values, the uniform location and an
1154 * offset (used for arrays, structs).
1155 */
1156 extern "C" GLint
1157 _mesa_get_uniform_location(struct gl_context *ctx,
1158 struct gl_shader_program *shProg,
1159 const GLchar *name)
1160 {
1161 GLint offset = 0, location = -1;
1162
1163 /* XXX we should return -1 if the uniform was declared, but not
1164 * actually used.
1165 */
1166
1167 /* XXX we need to be able to parse uniform names for structs and arrays
1168 * such as:
1169 * mymatrix[1]
1170 * mystruct.field1
1171 */
1172
1173 {
1174 /* handle 1-dimension arrays here... */
1175 char *c = strchr((char *)name, '[');
1176 if (c) {
1177 /* truncate name at [ */
1178 const GLint len = c - name;
1179 GLchar *newName = (GLchar *) malloc(len + 1);
1180 if (!newName)
1181 return -1; /* out of mem */
1182 memcpy(newName, name, len);
1183 newName[len] = 0;
1184
1185 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1186 if (location >= 0) {
1187 const GLint element = atoi(c + 1);
1188 if (element > 0) {
1189 /* get type of the uniform array element */
1190 const struct gl_program_parameter *p =
1191 get_uniform_parameter(shProg, location);
1192 if (p) {
1193 GLint rows, cols;
1194 get_matrix_dims(p->DataType, &rows, &cols);
1195 if (rows < 1)
1196 rows = 1;
1197 offset = element * rows;
1198 }
1199 }
1200 }
1201
1202 free(newName);
1203 }
1204 }
1205
1206 if (location < 0) {
1207 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1208 }
1209
1210 if (location < 0) {
1211 return -1;
1212 }
1213
1214 return _mesa_uniform_merge_location_offset(location, offset);
1215 }