GLenum *type, GLcharARB *nameOut)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_shader_program *shProg =
- _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
+ struct gl_shader_program *shProg;
+ if (maxLength < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
if (!shProg)
return;
}
}
+static GLenum
+resource_prop_from_uniform_prop(GLenum uni_prop)
+{
+ switch (uni_prop) {
+ case GL_UNIFORM_TYPE:
+ return GL_TYPE;
+ case GL_UNIFORM_SIZE:
+ return GL_ARRAY_SIZE;
+ case GL_UNIFORM_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+ case GL_UNIFORM_BLOCK_INDEX:
+ return GL_BLOCK_INDEX;
+ case GL_UNIFORM_OFFSET:
+ return GL_OFFSET;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ return GL_ARRAY_STRIDE;
+ case GL_UNIFORM_MATRIX_STRIDE:
+ return GL_MATRIX_STRIDE;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ return GL_IS_ROW_MAJOR;
+ case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
+ return GL_ATOMIC_COUNTER_BUFFER_INDEX;
+ default:
+ return 0;
+ }
+}
+
extern "C" void GLAPIENTRY
_mesa_GetActiveUniformsiv(GLuint program,
GLsizei uniformCount,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- GLsizei i;
-
- shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
- if (!shProg)
- return;
+ struct gl_program_resource *res;
+ GLenum res_prop;
if (uniformCount < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glGetUniformIndices(uniformCount < 0)");
+ "glGetActiveUniformsiv(uniformCount < 0)");
return;
}
- for (i = 0; i < uniformCount; i++) {
- GLuint index = uniformIndices[i];
-
- if (index >= shProg->NumUserUniformStorage) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
- return;
- }
- }
-
- for (i = 0; i < uniformCount; i++) {
- GLuint index = uniformIndices[i];
- const struct gl_uniform_storage *uni = &shProg->UniformStorage[index];
-
- switch (pname) {
- case GL_UNIFORM_TYPE:
- params[i] = uni->type->gl_type;
- break;
-
- case GL_UNIFORM_SIZE:
- /* array_elements is zero for non-arrays, but the API requires that 1 be
- * returned.
- */
- params[i] = MAX2(1, uni->array_elements);
- break;
-
- case GL_UNIFORM_NAME_LENGTH:
- params[i] = strlen(uni->name) + 1;
-
- /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
- * spec says:
- *
- * "If the active uniform is an array, the uniform name returned
- * in name will always be the name of the uniform array appended
- * with "[0]"."
- */
- if (uni->array_elements != 0)
- params[i] += 3;
- break;
-
- case GL_UNIFORM_BLOCK_INDEX:
- params[i] = uni->block_index;
- break;
-
- case GL_UNIFORM_OFFSET:
- params[i] = uni->offset;
- break;
-
- case GL_UNIFORM_ARRAY_STRIDE:
- params[i] = uni->array_stride;
- break;
-
- case GL_UNIFORM_MATRIX_STRIDE:
- params[i] = uni->matrix_stride;
- break;
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
+ if (!shProg)
+ return;
- case GL_UNIFORM_IS_ROW_MAJOR:
- params[i] = uni->row_major;
- break;
+ res_prop = resource_prop_from_uniform_prop(pname);
- case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
- if (!ctx->Extensions.ARB_shader_atomic_counters)
- goto invalid_enum;
- params[i] = uni->atomic_buffer_index;
+ for (int i = 0; i < uniformCount; i++) {
+ res = _mesa_program_resource_find_index(shProg, GL_UNIFORM,
+ uniformIndices[i]);
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
break;
-
- default:
- goto invalid_enum;
}
- }
- return;
-
- invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
+ if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i],
+ res_prop, ¶ms[i],
+ "glGetActiveUniformsiv"))
+ break;
+ }
}
-static bool
+static struct gl_uniform_storage *
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)
+ const char *caller)
{
- if (!shProg || !shProg->LinkStatus) {
+ if (shProg == NULL) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller);
- return false;
- }
-
- if (location == -1) {
- /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
- * spec says:
- *
- * "The error INVALID_OPERATION is generated if program has not been
- * linked successfully, or if location is not a valid location for
- * program."
- *
- * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
- * says:
- *
- * "If the value of location is -1, the Uniform* commands will
- * silently ignore the data passed in, and the current uniform
- * values will not be changed."
- *
- * Allowing -1 for the location parameter of glUniform allows
- * applications to avoid error paths in the case that, for example, some
- * uniform variable is removed by the compiler / linker after
- * optimization. In this case, the new value of the uniform is dropped
- * on the floor. For the case of glGetUniform, there is nothing
- * sensible to do for a location of -1.
- *
- * The negative_one_is_not_valid flag selects between the two behaviors.
- */
- if (negative_one_is_not_valid) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
- caller, location);
- }
-
- return false;
+ return NULL;
}
/* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec:
*/
if (count < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller);
- return false;
+ return NULL;
+ }
+
+ /* Check that the given location is in bounds of uniform remap table.
+ * Unlinked programs will have NumUniformRemapTable == 0, so we can take
+ * the shProg->LinkStatus check out of the main path.
+ */
+ if (unlikely(location >= (GLint) shProg->NumUniformRemapTable)) {
+ if (!shProg->LinkStatus)
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
+ caller);
+ else
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
+ caller, location);
+
+ return NULL;
+ }
+
+ if (location == -1) {
+ if (!shProg->LinkStatus)
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
+ caller);
+
+ return NULL;
}
/* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
* - if count is greater than one, and the uniform declared in the
* shader is not an array variable,
*/
- if (location < -1) {
+ if (location < -1 || !shProg->UniformRemapTable[location]) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
caller, location);
- return false;
- }
-
- /* Check that the given location is in bounds of uniform remap table. */
- if (location >= (GLint) shProg->NumUniformRemapTable) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
- caller, location);
- return false;
+ return NULL;
}
/* If the driver storage pointer in remap table is -1, we ignore silently.
*/
if (shProg->UniformRemapTable[location] ==
INACTIVE_UNIFORM_EXPLICIT_LOCATION)
- return false;
+ return NULL;
- _mesa_uniform_split_location_offset(shProg, location, loc, array_index);
+ struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location];
- if (shProg->UniformStorage[*loc].array_elements == 0 && count > 1) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(count > 1 for non-array, location=%d)",
- caller, location);
- return false;
- }
+ if (uni->array_elements == 0) {
+ if (count > 1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(count = %u for non-array \"%s\"@%d)",
+ caller, count, uni->name, location);
+ return NULL;
+ }
- /* If the uniform is an array, check that array_index is in bounds.
- * If not an array, check that array_index is zero.
- * array_index is unsigned so no need to check for less than zero.
- */
- unsigned limit = shProg->UniformStorage[*loc].array_elements;
- if (limit == 0)
- limit = 1;
- if (*array_index >= limit) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
- caller, location);
- return false;
+ assert((location - uni->remap_location) == 0);
+ *array_index = 0;
+ } else {
+ /* The array index specified by the uniform location is just the uniform
+ * location minus the base location of of the uniform.
+ */
+ *array_index = location - uni->remap_location;
+
+ /* If the uniform is an array, check that array_index is in bounds.
+ * array_index is unsigned so no need to check for less than zero.
+ */
+ if (*array_index >= uni->array_elements) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)",
+ caller, location);
+ return NULL;
+ }
}
- return true;
+ return uni;
}
/**
{
struct gl_shader_program *shProg =
_mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv");
- struct gl_uniform_storage *uni;
- unsigned loc, offset;
+ unsigned offset;
- if (!validate_uniform_parameters(ctx, shProg, location, 1,
- &loc, &offset, "glGetUniform", true))
- return;
+ struct gl_uniform_storage *const uni =
+ validate_uniform_parameters(ctx, shProg, location, 1,
+ &offset, "glGetUniform");
+ if (uni == NULL) {
+ /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1
+ * spec says:
+ *
+ * "The error INVALID_OPERATION is generated if program has not been
+ * linked successfully, or if location is not a valid location for
+ * program."
+ *
+ * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec
+ * says:
+ *
+ * "If the value of location is -1, the Uniform* commands will
+ * silently ignore the data passed in, and the current uniform
+ * values will not be changed."
+ *
+ * Allowing -1 for the location parameter of glUniform allows
+ * applications to avoid error paths in the case that, for example, some
+ * uniform variable is removed by the compiler / linker after
+ * optimization. In this case, the new value of the uniform is dropped
+ * on the floor. For the case of glGetUniform, there is nothing
+ * sensible to do for a location of -1.
+ *
+ * If the location was -1, validate_unfirom_parameters will return NULL
+ * without raising an error. Raise the error here.
+ */
+ if (location == -1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniform(location=%d)",
+ location);
+ }
- uni = &shProg->UniformStorage[loc];
+ return;
+ }
{
unsigned elements = (uni->type->is_sampler())
*/
if (returnType == uni->type->base_type
|| ((returnType == GLSL_TYPE_INT
- || returnType == GLSL_TYPE_UINT
- || returnType == GLSL_TYPE_SAMPLER)
+ || returnType == GLSL_TYPE_UINT)
&&
(uni->type->base_type == GLSL_TYPE_INT
|| uni->type->base_type == GLSL_TYPE_UINT
case GLSL_TYPE_FLOAT:
printf("%g ", v[i].f);
break;
+ case GLSL_TYPE_DOUBLE:
+ printf("%g ", *(double* )&v[i * 2].f);
+ break;
default:
assert(!"Should not get here.");
break;
*/
const unsigned components = MAX2(1, uni->type->vector_elements);
const unsigned vectors = MAX2(1, uni->type->matrix_columns);
+ const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1;
/* Store the data in the driver's requested type in the driver's storage
* areas.
*/
- unsigned src_vector_byte_stride = components * 4;
+ unsigned src_vector_byte_stride = components * 4 * dmul;
for (i = 0; i < uni->num_driver_storage; i++) {
struct gl_uniform_driver_storage *const store = &uni->driver_storage[i];
const unsigned extra_stride =
store->element_stride - (vectors * store->vector_stride);
const uint8_t *src =
- (uint8_t *) (&uni->storage[array_index * (components * vectors)].i);
+ (uint8_t *) (&uni->storage[array_index * (dmul * components * vectors)].i);
#if 0
printf("%s: %p[%d] components=%u vectors=%u count=%u vector_stride=%u "
dst += array_index * store->element_stride;
switch (store->format) {
- case uniform_native:
- case uniform_bool_int_0_1: {
+ case uniform_native: {
unsigned j;
unsigned v;
break;
}
- case uniform_int_float:
- case uniform_bool_float: {
+ case uniform_int_float: {
const int *isrc = (const int *) src;
unsigned j;
unsigned v;
break;
}
- case uniform_bool_int_0_not0: {
- const int *isrc = (const int *) src;
- unsigned j;
- unsigned v;
- unsigned c;
-
- for (j = 0; j < count; j++) {
- for (v = 0; v < vectors; v++) {
- for (c = 0; c < components; c++) {
- ((int *) dst)[c] = *isrc == 0 ? 0 : ~0;
- isrc++;
- }
-
- dst += store->vector_stride;
- }
-
- dst += extra_stride;
- }
- break;
- }
-
default:
assert(!"Should not get here.");
break;
}
}
+
+/**
+ * Return printable string for a given GLSL_TYPE_x
+ */
+static const char *
+glsl_type_name(enum glsl_base_type type)
+{
+ switch (type) {
+ case GLSL_TYPE_UINT:
+ return "uint";
+ case GLSL_TYPE_INT:
+ return "int";
+ case GLSL_TYPE_FLOAT:
+ return "float";
+ case GLSL_TYPE_DOUBLE:
+ return "double";
+ case GLSL_TYPE_BOOL:
+ return "bool";
+ case GLSL_TYPE_SAMPLER:
+ return "sampler";
+ case GLSL_TYPE_IMAGE:
+ return "image";
+ case GLSL_TYPE_ATOMIC_UINT:
+ return "atomic_uint";
+ case GLSL_TYPE_STRUCT:
+ return "struct";
+ case GLSL_TYPE_INTERFACE:
+ return "interface";
+ case GLSL_TYPE_ARRAY:
+ return "array";
+ case GLSL_TYPE_VOID:
+ return "void";
+ case GLSL_TYPE_ERROR:
+ return "error";
+ default:
+ return "other";
+ }
+}
+
+
/**
* Called via glUniform*() functions.
*/
extern "C" void
_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
GLint location, GLsizei count,
- const GLvoid *values, GLenum type)
+ const GLvoid *values,
+ enum glsl_base_type basicType,
+ unsigned src_components)
{
- unsigned loc, offset;
- unsigned components;
- unsigned src_components;
- enum glsl_base_type basicType;
- struct gl_uniform_storage *uni;
+ unsigned offset;
+ int size_mul = basicType == GLSL_TYPE_DOUBLE ? 2 : 1;
- if (!validate_uniform_parameters(ctx, shProg, location, count,
- &loc, &offset, "glUniform", false))
+ struct gl_uniform_storage *const uni =
+ validate_uniform_parameters(ctx, shProg, location, count,
+ &offset, "glUniform");
+ if (uni == NULL)
return;
- uni = &shProg->UniformStorage[loc];
+ if (uni->type->is_matrix()) {
+ /* Can't set matrix uniforms (like mat4) with glUniform */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform%u(uniform \"%s\"@%d is matrix)",
+ src_components, uni->name, location);
+ return;
+ }
/* Verify that the types are compatible.
*/
- switch (type) {
- case GL_FLOAT:
- basicType = GLSL_TYPE_FLOAT;
- src_components = 1;
- break;
- case GL_FLOAT_VEC2:
- basicType = GLSL_TYPE_FLOAT;
- src_components = 2;
- break;
- case GL_FLOAT_VEC3:
- basicType = GLSL_TYPE_FLOAT;
- src_components = 3;
- break;
- case GL_FLOAT_VEC4:
- basicType = GLSL_TYPE_FLOAT;
- src_components = 4;
- break;
- case GL_UNSIGNED_INT:
- basicType = GLSL_TYPE_UINT;
- src_components = 1;
- break;
- case GL_UNSIGNED_INT_VEC2:
- basicType = GLSL_TYPE_UINT;
- src_components = 2;
- break;
- case GL_UNSIGNED_INT_VEC3:
- basicType = GLSL_TYPE_UINT;
- src_components = 3;
- break;
- case GL_UNSIGNED_INT_VEC4:
- basicType = GLSL_TYPE_UINT;
- src_components = 4;
- break;
- case GL_INT:
- basicType = GLSL_TYPE_INT;
- src_components = 1;
- break;
- case GL_INT_VEC2:
- basicType = GLSL_TYPE_INT;
- src_components = 2;
- break;
- case GL_INT_VEC3:
- basicType = GLSL_TYPE_INT;
- src_components = 3;
- break;
- case GL_INT_VEC4:
- basicType = GLSL_TYPE_INT;
- src_components = 4;
- break;
- case GL_BOOL:
- case GL_BOOL_VEC2:
- case GL_BOOL_VEC3:
- case GL_BOOL_VEC4:
- case GL_FLOAT_MAT2:
- case GL_FLOAT_MAT2x3:
- case GL_FLOAT_MAT2x4:
- case GL_FLOAT_MAT3x2:
- case GL_FLOAT_MAT3:
- case GL_FLOAT_MAT3x4:
- case GL_FLOAT_MAT4x2:
- case GL_FLOAT_MAT4x3:
- case GL_FLOAT_MAT4:
- default:
- _mesa_problem(NULL, "Invalid type in %s", __func__);
- return;
- }
+ const unsigned components = uni->type->is_sampler()
+ ? 1 : uni->type->vector_elements;
- if (uni->type->is_sampler()) {
- components = 1;
- } else {
- components = uni->type->vector_elements;
+ if (components != src_components) {
+ /* glUniformN() must match float/vecN type */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform%u(\"%s\"@%u has %u components, not %u)",
+ src_components, uni->name, location,
+ components, src_components);
+ return;
}
bool match;
switch (uni->type->base_type) {
case GLSL_TYPE_BOOL:
- match = true;
+ match = (basicType != GLSL_TYPE_DOUBLE);
break;
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
break;
}
- if (uni->type->is_matrix() || components != src_components || !match) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
+ if (!match) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform%u(\"%s\"@%d is %s, not %s)",
+ src_components, uni->name, location,
+ glsl_type_name(uni->type->base_type),
+ glsl_type_name(basicType));
return;
}
- if (ctx->_Shader->Flags & GLSL_UNIFORMS) {
+ if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
log_uniform(values, basicType, components, 1, count,
false, shProg, location, uni);
}
* GL_INVALID_VALUE error and ignore the command.
*/
if (uni->type->is_sampler()) {
- int i;
-
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
const unsigned texUnit = ((unsigned *) values)[i];
/* check that the sampler (tex unit index) is legal */
}
if (uni->type->is_image()) {
- int i;
-
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
const int unit = ((GLint *) values)[i];
/* check that the image unit is legal */
/* Store the data in the "actual type" backing storage for the uniform.
*/
if (!uni->type->is_boolean()) {
- memcpy(&uni->storage[components * offset], values,
- sizeof(uni->storage[0]) * components * count);
+ memcpy(&uni->storage[size_mul * components * offset], values,
+ sizeof(uni->storage[0]) * components * count * size_mul);
} else {
const union gl_constant_value *src =
(const union gl_constant_value *) values;
union gl_constant_value *dst = &uni->storage[components * offset];
const unsigned elems = components * count;
- unsigned i;
- for (i = 0; i < elems; i++) {
+ for (unsigned i = 0; i < elems; i++) {
if (basicType == GLSL_TYPE_FLOAT) {
- dst[i].i = src[i].f != 0.0f ? 1 : 0;
+ dst[i].i = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0;
} else {
- dst[i].i = src[i].i != 0 ? 1 : 0;
+ dst[i].i = src[i].i != 0 ? ctx->Const.UniformBooleanTrue : 0;
}
}
}
* the changes through.
*/
if (uni->type->is_sampler()) {
- int i;
-
bool flushed = false;
- for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_shader *const sh = shProg->_LinkedShaders[i];
- int j;
/* If the shader stage doesn't use the sampler uniform, skip this.
*/
if (sh == NULL || !uni->sampler[i].active)
continue;
- for (j = 0; j < count; j++) {
+ for (int j = 0; j < count; j++) {
sh->SamplerUnits[uni->sampler[i].index + offset + j] =
((unsigned *) values)[j];
}
* been modified.
*/
bool changed = false;
- for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) {
+ for (unsigned j = 0; j < ARRAY_SIZE(prog->SamplerUnits); j++) {
if ((sh->active_samplers & (1U << j)) != 0
&& (prog->SamplerUnits[j] != sh->SamplerUnits[j])) {
changed = true;
* uniforms to image units present in the shader data structure.
*/
if (uni->type->is_image()) {
- int i, j;
-
- for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
if (uni->image[i].active) {
struct gl_shader *sh = shProg->_LinkedShaders[i];
- for (j = 0; j < count; j++)
+ for (int j = 0; j < count; j++)
sh->ImageUnits[uni->image[i].index + offset + j] =
((GLint *) values)[j];
}
_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)
+ GLboolean transpose,
+ const GLvoid *values, GLenum type)
{
- unsigned loc, offset;
+ unsigned offset;
unsigned vectors;
unsigned components;
unsigned elements;
- struct gl_uniform_storage *uni;
-
- if (!validate_uniform_parameters(ctx, shProg, location, count,
- &loc, &offset, "glUniformMatrix", false))
+ int size_mul;
+ struct gl_uniform_storage *const uni =
+ validate_uniform_parameters(ctx, shProg, location, count,
+ &offset, "glUniformMatrix");
+ if (uni == NULL)
return;
- uni = &shProg->UniformStorage[loc];
if (!uni->type->is_matrix()) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUniformMatrix(non-matrix uniform)");
return;
}
+ assert(type == GL_FLOAT || type == GL_DOUBLE);
+ size_mul = type == GL_DOUBLE ? 2 : 1;
+
assert(!uni->type->is_sampler());
vectors = uni->type->matrix_columns;
components = uni->type->vector_elements;
}
/* GL_INVALID_VALUE is generated if `transpose' is not GL_FALSE.
- * http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml */
- if (ctx->API == API_OPENGLES
- || (ctx->API == API_OPENGLES2 && ctx->Version < 30)) {
- if (transpose) {
+ * http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml
+ */
+ if (transpose) {
+ if (ctx->API == API_OPENGLES2 && ctx->Version < 30) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glUniformMatrix(matrix transpose is not GL_FALSE)");
return;
}
}
- if (ctx->_Shader->Flags & GLSL_UNIFORMS) {
- log_uniform(values, GLSL_TYPE_FLOAT, components, vectors, count,
+ if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
+ log_uniform(values, uni->type->base_type, components, vectors, count,
bool(transpose), shProg, location, uni);
}
if (!transpose) {
memcpy(&uni->storage[elements * offset], values,
- sizeof(uni->storage[0]) * elements * count);
- } else {
+ sizeof(uni->storage[0]) * elements * count * size_mul);
+ } else if (type == GL_FLOAT) {
/* Copy and transpose the matrix.
*/
- const float *src = values;
+ const float *src = (const float *)values;
float *dst = &uni->storage[elements * offset].f;
+ for (int i = 0; i < count; i++) {
+ for (unsigned r = 0; r < rows; r++) {
+ for (unsigned c = 0; c < cols; c++) {
+ dst[(c * components) + r] = src[c + (r * vectors)];
+ }
+ }
+
+ dst += elements;
+ src += elements;
+ }
+ } else {
+ assert(type == GL_DOUBLE);
+ const double *src = (const double *)values;
+ double *dst = (double *)&uni->storage[elements * offset].f;
+
for (int i = 0; i < count; i++) {
for (unsigned r = 0; r < rows; r++) {
for (unsigned c = 0; c < cols; c++) {
*
* Returns the uniform index into UniformStorage (also the
* glGetActiveUniformsiv uniform index), and stores the referenced
- * array offset in *offset, or GL_INVALID_INDEX (-1). Those two
- * return values can be encoded into a uniform location for
- * glUniform* using _mesa_uniform_merge_location_offset(index, offset).
+ * array offset in *offset, or GL_INVALID_INDEX (-1).
*/
extern "C" unsigned
-_mesa_get_uniform_location(struct gl_context *ctx,
- struct gl_shader_program *shProg,
+_mesa_get_uniform_location(struct gl_shader_program *shProg,
const GLchar *name,
unsigned *out_offset)
{
_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
char *errMsg, size_t errMsgLength)
{
- const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-
- memset(unit_types, 0, sizeof(unit_types));
-
- for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) {
- const struct gl_uniform_storage *const storage =
- &shProg->UniformStorage[i];
- const glsl_type *const t = (storage->type->is_array())
- ? storage->type->fields.array : storage->type;
-
- if (!t->is_sampler())
- continue;
-
- const unsigned count = MAX2(1, storage->type->array_size());
- for (unsigned j = 0; j < count; j++) {
- const unsigned unit = storage->storage[j].i;
-
- /* The types of the samplers associated with a particular texture
- * unit must be an exact match. Page 74 (page 89 of the PDF) of the
- * OpenGL 3.3 core spec says:
- *
- * "It is not allowed to have variables of different sampler
- * types pointing to the same texture image unit within a program
- * object."
- */
- if (unit_types[unit] == NULL) {
- unit_types[unit] = t;
- } else if (unit_types[unit] != t) {
- _mesa_snprintf(errMsg, errMsgLength,
- "Texture unit %d is accessed both as %s and %s",
- unit, unit_types[unit]->name, t->name);
- return false;
- }
- }
+ /* Shader does not have samplers. */
+ if (shProg->NumUserUniformStorage == 0)
+ return true;
+
+ if (!shProg->SamplersValidated) {
+ _mesa_snprintf(errMsg, errMsgLength,
+ "active samplers with a different type "
+ "refer to the same texture image unit");
+ return false;
}
-
return true;
}