2 * Mesa 3-D graphics library
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
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
25 #include "main/core.h"
26 #include "main/context.h"
28 #include "ir_uniform.h"
29 #include "../glsl/program.h"
30 #include "../glsl/ir_uniform.h"
33 #include "main/image.h"
34 #include "main/shaderapi.h"
35 #include "main/shaderobj.h"
39 extern "C" void GLAPIENTRY
40 _mesa_GetActiveUniformARB(GLhandleARB program
, GLuint index
,
41 GLsizei maxLength
, GLsizei
*length
, GLint
*size
,
42 GLenum
*type
, GLcharARB
*nameOut
)
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
;
52 if (!shProg
->Uniforms
|| index
>= shProg
->Uniforms
->NumUniforms
) {
53 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetActiveUniform(index)");
57 param
= get_uniform_parameter(shProg
, index
);
61 const struct gl_uniform
*const uni
= &shProg
->Uniforms
->Uniforms
[index
];
64 _mesa_copy_string(nameOut
, maxLength
, length
, param
->Name
);
68 GLint typeSize
= _mesa_sizeof_glsl_type(uni
->Type
->gl_type
);
69 if ((GLint
) param
->Size
> typeSize
) {
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.
75 typeSize
= (typeSize
+ 3) & ~3;
77 /* Note that the returned size is in units of the <type>, not bytes */
78 *size
= param
->Size
/ typeSize
;
82 *type
= uni
->Type
->gl_type
;
87 base_uniform_type(GLenum type
)
100 case GL_FLOAT_MAT2x3
:
101 case GL_FLOAT_MAT2x4
:
102 case GL_FLOAT_MAT3x2
:
104 case GL_FLOAT_MAT3x4
:
105 case GL_FLOAT_MAT4x2
:
106 case GL_FLOAT_MAT4x3
:
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
;
120 _mesa_problem(NULL
, "Invalid type in base_uniform_type()");
126 is_boolean_type(GLenum type
)
140 is_sampler_type(GLenum type
)
144 case GL_INT_SAMPLER_1D
:
145 case GL_UNSIGNED_INT_SAMPLER_1D
:
147 case GL_INT_SAMPLER_2D
:
148 case GL_UNSIGNED_INT_SAMPLER_2D
:
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
:
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
199 find_uniform_parameter_pos(struct gl_shader_program
*shProg
, GLint index
,
200 struct gl_program
**progOut
, GLint
*posOut
)
202 struct gl_program
*prog
= NULL
;
205 if (!shProg
->Uniforms
||
207 index
>= (GLint
) shProg
->Uniforms
->NumUniforms
) {
211 pos
= shProg
->Uniforms
->Uniforms
[index
].VertPos
;
213 prog
= shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->Program
;
216 pos
= shProg
->Uniforms
->Uniforms
[index
].FragPos
;
218 prog
= shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->Program
;
221 pos
= shProg
->Uniforms
->Uniforms
[index
].GeomPos
;
223 prog
= shProg
->_LinkedShaders
[MESA_SHADER_GEOMETRY
]->Program
;
228 if (!prog
|| pos
< 0)
229 return GL_FALSE
; /* should really never happen */
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
243 const struct gl_program_parameter
*
244 get_uniform_parameter(struct gl_shader_program
*shProg
, GLint index
)
246 struct gl_program
*prog
;
249 if (find_uniform_parameter_pos(shProg
, index
, &prog
, &progPos
))
250 return &prog
->Parameters
->Parameters
[progPos
];
256 get_vector_elements(GLenum type
)
262 case GL_UNSIGNED_INT
:
263 default: /* Catch all the various sampler types. */
269 case GL_UNSIGNED_INT_VEC2
:
275 case GL_UNSIGNED_INT_VEC3
:
281 case GL_UNSIGNED_INT_VEC4
:
287 get_matrix_dims(GLenum type
, GLint
*rows
, GLint
*cols
)
293 case GL_FLOAT_MAT2x3
:
297 case GL_FLOAT_MAT2x4
:
305 case GL_FLOAT_MAT3x2
:
309 case GL_FLOAT_MAT3x4
:
317 case GL_FLOAT_MAT4x2
:
321 case GL_FLOAT_MAT4x3
:
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.
336 get_uniform_rows_cols(const struct gl_program_parameter
*p
,
337 GLint
*rows
, GLint
*cols
)
339 get_matrix_dims(p
->DataType
, rows
, cols
);
340 if (*rows
== 0 && *cols
== 0) {
341 /* not a matrix type, probably a float or vector */
343 *cols
= get_vector_elements(p
->DataType
);
348 validate_uniform_parameters(struct gl_context
*ctx
,
349 struct gl_shader_program
*shProg
,
350 GLint location
, GLsizei count
,
352 unsigned *array_index
,
354 bool negative_one_is_not_valid
)
356 if (!shProg
|| !shProg
->LinkStatus
) {
357 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(program not linked)", caller
);
361 if (location
== -1) {
362 /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
365 * "The error INVALID_OPERATION is generated if program has not been
366 * linked successfully, or if location is not a valid location for
369 * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
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."
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.
383 * The negative_one_is_not_valid flag selects between the two behaviors.
385 if (negative_one_is_not_valid
) {
386 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(location=%d)",
393 /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
395 * "If a negative number is provided where an argument of type sizei or
396 * sizeiptr is specified, the error INVALID_VALUE is generated."
399 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(count < 0)", caller
);
403 /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
405 * "If any of the following conditions occur, an INVALID_OPERATION
406 * error is generated by the Uniform* commands, and no uniform values
411 * - if no variable with a location of location exists in the
412 * program object currently in use and location is not -1,
415 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(location=%d)",
420 _mesa_uniform_split_location_offset(location
, loc
, array_index
);
422 if (*loc
>= shProg
->Uniforms
->NumUniforms
) {
423 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(location=%d)",
432 * Called via glGetUniform[fiui]v() to get the current value of a uniform.
435 _mesa_get_uniform(struct gl_context
*ctx
, GLuint program
, GLint location
,
436 GLsizei bufSize
, GLenum returnType
, GLvoid
*paramsOut
)
438 struct gl_shader_program
*shProg
=
439 _mesa_lookup_shader_program_err(ctx
, program
, "glGetUniformfv");
440 struct gl_program
*prog
;
442 unsigned loc
, offset
;
444 if (!validate_uniform_parameters(ctx
, shProg
, location
, 1,
445 &loc
, &offset
, "glGetUniform", true))
448 if (!find_uniform_parameter_pos(shProg
, loc
, &prog
, ¶mPos
)) {
449 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetUniformfv(location)");
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
;
459 values
= prog
->Parameters
->ParameterValues
+ paramPos
+ offset
;
461 get_uniform_rows_cols(p
, &rows
, &cols
);
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
);
471 if (ctx
->Const
.NativeIntegers
) {
472 storage_type
= base_uniform_type(p
->DataType
);
474 storage_type
= GL_FLOAT
;
478 for (i
= 0; i
< rows
; i
++) {
479 for (j
= 0; j
< cols
; j
++ ) {
480 void *out
= (char *)paramsOut
+ 4 * k
;
482 switch (returnType
) {
484 switch (storage_type
) {
486 *(float *)out
= values
[i
][j
].f
;
489 case GL_BOOL
: /* boolean is just an integer 1 or 0. */
490 *(float *)out
= values
[i
][j
].i
;
492 case GL_UNSIGNED_INT
:
493 *(float *)out
= values
[i
][j
].u
;
499 case GL_UNSIGNED_INT
:
500 switch (storage_type
) {
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
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"
513 * That section, on page 248, says:
515 * "If GetIntegerv or GetInteger64v are called,
516 * a floating-point value is rounded to the
517 * nearest integer..."
519 *(int *)out
= IROUND(values
[i
][j
].f
);
523 case GL_UNSIGNED_INT
:
525 /* type conversions for these to int/uint are just
528 *(int *)out
= values
[i
][j
].i
;
542 log_uniform(const void *values
, enum glsl_base_type basicType
,
543 unsigned rows
, unsigned cols
, unsigned count
,
545 const struct gl_shader_program
*shProg
,
547 const struct gl_uniform_storage
*uni
)
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";
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))
564 printf("%u ", v
[i
].u
);
567 printf("%d ", v
[i
].i
);
569 case GLSL_TYPE_FLOAT
:
570 printf("%g ", v
[i
].f
);
573 assert(!"Should not get here.");
583 log_program_parameters(const struct gl_shader_program
*shProg
)
585 static const char *stages
[] = {
586 "vertex", "fragment", "geometry"
589 assert(Elements(stages
) == MESA_SHADER_TYPES
);
591 for (unsigned i
= 0; i
< MESA_SHADER_TYPES
; i
++) {
592 if (shProg
->_LinkedShaders
[i
] == NULL
)
595 const struct gl_program
*const prog
= shProg
->_LinkedShaders
[i
]->Program
;
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
);
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.
619 compatible_types(GLenum userType
, GLenum targetType
)
621 if (userType
== targetType
)
624 if (targetType
== GL_BOOL
&& (userType
== GL_FLOAT
||
625 userType
== GL_UNSIGNED_INT
||
629 if (targetType
== GL_BOOL_VEC2
&& (userType
== GL_FLOAT_VEC2
||
630 userType
== GL_UNSIGNED_INT_VEC2
||
631 userType
== GL_INT_VEC2
))
634 if (targetType
== GL_BOOL_VEC3
&& (userType
== GL_FLOAT_VEC3
||
635 userType
== GL_UNSIGNED_INT_VEC3
||
636 userType
== GL_INT_VEC3
))
639 if (targetType
== GL_BOOL_VEC4
&& (userType
== GL_FLOAT_VEC4
||
640 userType
== GL_UNSIGNED_INT_VEC4
||
641 userType
== GL_INT_VEC4
))
644 if (is_sampler_type(targetType
) && userType
== GL_INT
)
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'
661 set_program_uniform(struct gl_context
*ctx
, struct gl_program
*program
,
662 GLint index
, GLint offset
,
663 GLenum type
, GLsizei count
, GLint elems
,
666 const struct gl_program_parameter
*param
=
667 &program
->Parameters
->Parameters
[index
];
673 if (!compatible_types(type
, param
->DataType
)) {
674 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUniform(type mismatch)");
678 if (index
+ offset
> (GLint
) program
->Parameters
->Size
) {
683 if (param
->Type
== PROGRAM_SAMPLER
) {
684 /* This controls which texture unit which is used by a sampler */
685 GLboolean changed
= GL_FALSE
;
688 /* this should have been caught by the compatible_types() check */
689 ASSERT(type
== GL_INT
);
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
];
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')",
705 /* This maps a sampler to a texture unit: */
706 if (sampler
< MAX_SAMPLERS
) {
708 printf("Set program %p sampler %d '%s' to unit %u\n",
709 program
, sampler
, param
->Name
, texUnit
);
711 if (program
->SamplerUnits
[sampler
] != texUnit
) {
712 program
->SamplerUnits
[sampler
] = texUnit
;
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.
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
730 (void) ctx
->Driver
.ProgramStringNotify(ctx
, program
->Target
, program
);
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
);
741 if ((GLint
) param
->Size
> typeSize
) {
743 /* we'll ignore extra data below */
746 /* non-array: count must be at most one; count == 0 is handled
750 _mesa_error(ctx
, GL_INVALID_OPERATION
,
751 "glUniform(uniform '%s' is not an array)",
757 /* loop over number of array elements */
758 for (k
= 0; k
< count
; k
++) {
759 gl_constant_value
*uniformVal
;
761 if (offset
+ k
>= slots
) {
762 /* Extra array data is ignored */
766 /* uniformVal (the destination) is always gl_constant_value[4] */
767 uniformVal
= program
->Parameters
->ParameterValues
[index
+ offset
+ k
];
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
];
775 uniformVal
[i
].i
= iValues
[i
];
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
];
784 uniformVal
[i
].u
= iValues
[i
];
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
];
795 /* if the uniform is bool-valued, convert to 1 or 0 */
797 for (i
= 0; i
< elems
; i
++) {
798 if (basicType
== GL_FLOAT
)
799 uniformVal
[i
].b
= uniformVal
[i
].f
!= 0.0f
? 1 : 0;
801 uniformVal
[i
].b
= uniformVal
[i
].u
? 1 : 0;
803 if (ctx
->Const
.NativeIntegers
)
805 uniformVal
[i
].b
? ctx
->Const
.UniformBooleanTrue
: 0;
807 uniformVal
[i
].f
= uniformVal
[i
].b
? 1.0f
: 0.0f
;
815 * Propagate some values from uniform backing storage to driver storage
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,
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.
829 _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage
*uni
,
830 unsigned array_index
,
835 /* vector_elements and matrix_columns can be 0 for samplers.
837 const unsigned components
= MAX2(1, uni
->type
->vector_elements
);
838 const unsigned vectors
= MAX2(1, uni
->type
->matrix_columns
);
840 /* Store the data in the driver's requested type in the driver's storage
843 unsigned src_vector_byte_stride
= components
* 4;
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
);
851 (uint8_t *) (&uni
->storage
[array_index
* (components
* vectors
)].i
);
854 printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
856 __func__
, dst
, array_index
, components
,
857 vectors
, count
, store
->vector_stride
, extra_stride
);
860 dst
+= array_index
* store
->element_stride
;
862 switch (store
->format
) {
864 case uniform_bool_int_0_1
: {
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
;
880 case uniform_int_float
:
881 case uniform_bool_float
: {
882 const int *isrc
= (const int *) src
;
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
;
894 dst
+= store
->vector_stride
;
902 case uniform_bool_int_0_not0
: {
903 const int *isrc
= (const int *) src
;
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;
915 dst
+= store
->vector_stride
;
924 assert(!"Should not get here.");
931 * Called via glUniform*() functions.
934 _mesa_uniform(struct gl_context
*ctx
, struct gl_shader_program
*shProg
,
935 GLint location
, GLsizei count
,
936 const GLvoid
*values
, GLenum type
)
938 struct gl_uniform
*uniform
;
940 unsigned loc
, offset
;
942 ASSERT_OUTSIDE_BEGIN_END(ctx
);
944 if (!validate_uniform_parameters(ctx
, shProg
, location
, count
,
945 &loc
, &offset
, "glUniform", false))
948 elems
= _mesa_sizeof_glsl_type(type
);
950 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
952 uniform
= &shProg
->Uniforms
->Uniforms
[loc
];
954 if (ctx
->Shader
.Flags
& GLSL_UNIFORMS
) {
955 const GLenum basicType
= base_uniform_type(type
);
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
++) {
965 else if (basicType
== GL_UNSIGNED_INT
) {
966 const GLuint
*v
= (const GLuint
*) values
;
967 for (i
= 0; i
< count
* elems
; i
++) {
972 const GLfloat
*v
= (const GLfloat
*) values
;
973 assert(basicType
== GL_FLOAT
);
974 for (i
= 0; i
< count
* elems
; i
++) {
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:
984 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]) {
985 /* convert uniform location to program parameter index */
986 GLint index
= uniform
->VertPos
;
988 set_program_uniform(ctx
,
989 shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->Program
,
990 index
, offset
, type
, count
, elems
, values
);
994 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]) {
995 /* convert uniform location to program parameter index */
996 GLint index
= uniform
->FragPos
;
998 set_program_uniform(ctx
,
999 shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->Program
,
1000 index
, offset
, type
, count
, elems
, values
);
1004 if (shProg
->_LinkedShaders
[MESA_SHADER_GEOMETRY
]) {
1005 /* convert uniform location to program parameter index */
1006 GLint index
= uniform
->GeomPos
;
1008 set_program_uniform(ctx
,
1009 shProg
->_LinkedShaders
[MESA_SHADER_GEOMETRY
]->Program
,
1010 index
, offset
, type
, count
, elems
, values
);
1014 uniform
->Initialized
= GL_TRUE
;
1018 * Set a matrix-valued program parameter.
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
)
1026 GLuint mat
, row
, col
;
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
);
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)");
1042 if ((GLint
) param
->Size
<= typeSize
) {
1043 /* non-array: count must be at most one; count == 0 is handled
1047 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1048 "glUniformMatrix(uniform is not an array)");
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...
1059 /* loop over matrices */
1060 for (mat
= 0; mat
< count
; mat
++) {
1063 for (col
= 0; col
< cols
; col
++) {
1065 if (offset
>= slots
) {
1066 /* Ignore writes beyond the end of (the used part of) an array */
1069 v
= (GLfloat
*) program
->Parameters
->ParameterValues
[index
+ offset
];
1070 for (row
= 0; row
< rows
; row
++) {
1072 v
[row
] = values
[src
+ row
* cols
+ col
];
1075 v
[row
] = values
[src
+ col
* rows
+ row
];
1082 src
+= rows
* cols
; /* next matrix */
1087 * Called by glUniformMatrix*() functions.
1088 * Note: cols=2, rows=4 ==> array[2] of vec4
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
)
1096 struct gl_uniform
*uniform
;
1097 unsigned loc
, offset
;
1099 ASSERT_OUTSIDE_BEGIN_END(ctx
);
1101 if (!validate_uniform_parameters(ctx
, shProg
, location
, count
,
1102 &loc
, &offset
, "glUniformMatrix", false))
1105 if (values
== NULL
) {
1106 _mesa_error(ctx
, GL_INVALID_VALUE
, "glUniformMatrix");
1110 FLUSH_VERTICES(ctx
, _NEW_PROGRAM_CONSTANTS
);
1112 uniform
= &shProg
->Uniforms
->Uniforms
[loc
];
1114 if (shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]) {
1115 /* convert uniform location to program parameter index */
1116 GLint index
= uniform
->VertPos
;
1118 set_program_uniform_matrix(ctx
,
1119 shProg
->_LinkedShaders
[MESA_SHADER_VERTEX
]->Program
,
1121 count
, rows
, cols
, transpose
, values
);
1125 if (shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]) {
1126 /* convert uniform location to program parameter index */
1127 GLint index
= uniform
->FragPos
;
1129 set_program_uniform_matrix(ctx
,
1130 shProg
->_LinkedShaders
[MESA_SHADER_FRAGMENT
]->Program
,
1132 count
, rows
, cols
, transpose
, values
);
1136 if (shProg
->_LinkedShaders
[MESA_SHADER_GEOMETRY
]) {
1137 /* convert uniform location to program parameter index */
1138 GLint index
= uniform
->GeomPos
;
1140 set_program_uniform_matrix(ctx
,
1141 shProg
->_LinkedShaders
[MESA_SHADER_GEOMETRY
]->Program
,
1143 count
, rows
, cols
, transpose
, values
);
1147 uniform
->Initialized
= GL_TRUE
;
1151 * Called via glGetUniformLocation().
1153 * The return value will encode two values, the uniform location and an
1154 * offset (used for arrays, structs).
1157 _mesa_get_uniform_location(struct gl_context
*ctx
,
1158 struct gl_shader_program
*shProg
,
1161 GLint offset
= 0, location
= -1;
1163 /* XXX we should return -1 if the uniform was declared, but not
1167 /* XXX we need to be able to parse uniform names for structs and arrays
1174 /* handle 1-dimension arrays here... */
1175 char *c
= strchr((char *)name
, '[');
1177 /* truncate name at [ */
1178 const GLint len
= c
- name
;
1179 GLchar
*newName
= (GLchar
*) malloc(len
+ 1);
1181 return -1; /* out of mem */
1182 memcpy(newName
, name
, len
);
1185 location
= _mesa_lookup_uniform(shProg
->Uniforms
, newName
);
1186 if (location
>= 0) {
1187 const GLint element
= atoi(c
+ 1);
1189 /* get type of the uniform array element */
1190 const struct gl_program_parameter
*p
=
1191 get_uniform_parameter(shProg
, location
);
1194 get_matrix_dims(p
->DataType
, &rows
, &cols
);
1197 offset
= element
* rows
;
1207 location
= _mesa_lookup_uniform(shProg
->Uniforms
, name
);
1214 return _mesa_uniform_merge_location_offset(location
, offset
);