From 9fa41f0742b7486e462e088a66bef8cebdf114f5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 23 Aug 2011 13:46:12 -0700 Subject: mesa: Fix glGetUniform() type conversions. We were primarily failing to convert in the NativeIntegers case, which this fixes. However, we were also just truncating float uniforms when converting to integer, which does not appear to be the correct behavior. Note, however, that the NVIDIA drivers also truncate instead of rounding. GL_DOUBLE return type is dropped because it was never used and completely broken. It can be added when there's test code. Fixes piglit ARB_shader_objects/getuniform v2: This is a rewrite of my previous glGetUniform patch, which Ken pointed out missed storage_type-based conversions to integer, which was totally broken still thanks to a typo in the testcase. v3: Quote the spec justifying the rounding behavior. Acked-by: Kenneth Graunke Acked-by: Ian Romanick --- src/mesa/main/uniforms.c | 137 +++++++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 58 deletions(-) (limited to 'src/mesa/main/uniforms.c') diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index cda840fe2d2..fe1ce6d7b2c 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -55,17 +55,24 @@ static GLenum base_uniform_type(GLenum type) { switch (type) { -#if 0 /* not needed, for now */ case GL_BOOL: case GL_BOOL_VEC2: case GL_BOOL_VEC3: case GL_BOOL_VEC4: return GL_BOOL; -#endif case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: case GL_FLOAT_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: return GL_FLOAT; case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_VEC2: @@ -408,8 +415,12 @@ get_uniform(struct gl_context *ctx, GLuint program, GLint location, else { const struct gl_program_parameter *p = &prog->Parameters->Parameters[paramPos]; + gl_constant_value (*values)[4]; GLint rows, cols, i, j, k; GLsizei numBytes; + GLenum storage_type; + + values = prog->Parameters->ParameterValues + paramPos + offset; get_uniform_rows_cols(p, &rows, &cols); @@ -421,62 +432,72 @@ get_uniform(struct gl_context *ctx, GLuint program, GLint location, return; } - switch (returnType) { - case GL_FLOAT: - { - GLfloat *params = (GLfloat *) paramsOut; - k = 0; - for (i = 0; i < rows; i++) { - const int base = paramPos + offset + i; - for (j = 0; j < cols; j++ ) { - params[k++] = prog->Parameters->ParameterValues[base][j].f; - } - } - } - break; - case GL_DOUBLE: - { - GLfloat *params = (GLfloat *) paramsOut; - k = 0; - for (i = 0; i < rows; i++) { - const int base = paramPos + offset + i; - for (j = 0; j < cols; j++ ) { - params[k++] = (GLdouble) - prog->Parameters->ParameterValues[base][j].f; - } - } - } - break; - case GL_INT: - { - GLint *params = (GLint *) paramsOut; - k = 0; - for (i = 0; i < rows; i++) { - const int base = paramPos + offset + i; - for (j = 0; j < cols; j++ ) { - params[k++] = ctx->Const.NativeIntegers ? - prog->Parameters->ParameterValues[base][j].i : - (GLint) prog->Parameters->ParameterValues[base][j].f; - } - } - } - break; - case GL_UNSIGNED_INT: - { - GLuint *params = (GLuint *) paramsOut; - k = 0; - for (i = 0; i < rows; i++) { - const int base = paramPos + offset + i; - for (j = 0; j < cols; j++ ) { - params[k++] = ctx->Const.NativeIntegers ? - prog->Parameters->ParameterValues[base][j].u : - (GLuint) prog->Parameters->ParameterValues[base][j].f; - } - } - } - break; - default: - _mesa_problem(ctx, "bad returnType in get_uniform()"); + if (ctx->Const.NativeIntegers) { + storage_type = base_uniform_type(p->DataType); + } else { + storage_type = GL_FLOAT; + } + + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++ ) { + void *out = (char *)paramsOut + 4 * k; + + switch (returnType) { + case GL_FLOAT: + switch (storage_type) { + case GL_FLOAT: + *(float *)out = values[i][j].f; + break; + case GL_INT: + case GL_BOOL: /* boolean is just an integer 1 or 0. */ + *(float *)out = values[i][j].i; + break; + case GL_UNSIGNED_INT: + *(float *)out = values[i][j].u; + break; + } + break; + + case GL_INT: + case GL_UNSIGNED_INT: + switch (storage_type) { + case GL_FLOAT: + /* While the GL 3.2 core spec doesn't explicitly + * state how conversion of float uniforms to integer + * values works, in section 6.2 "State Tables" on + * page 267 it says: + * + * "Unless otherwise specified, when floating + * point state is returned as integer values or + * integer state is returned as floating-point + * values it is converted in the fashion + * described in section 6.1.2" + * + * That section, on page 248, says: + * + * "If GetIntegerv or GetInteger64v are called, + * a floating-point value is rounded to the + * nearest integer..." + */ + *(int *)out = IROUND(values[i][j].f); + break; + + case GL_INT: + case GL_UNSIGNED_INT: + case GL_BOOL: + /* type conversions for these to int/uint are just + * copying the data. + */ + *(int *)out = values[i][j].i; + break; + break; + } + break; + } + + k++; + } } } } -- cgit v1.2.3