[Mesa-dev] [PATCH 04/10] mesa: Fix glGetUniform() type conversions.

Eric Anholt eric at anholt.net
Tue Aug 23 18:25:51 PDT 2011


We were primarily failing to convert in the NativeIntegers case, which
this fixes.  However, the GL 3.2 core specification is unclear on what
should happen when asked to convert a floating point uniform to
integer.  I assume the result should be like glGetInteger's conversion
of floating point values to integers.

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.
---
 src/mesa/main/uniforms.c |  126 +++++++++++++++++++++++++---------------------
 1 files changed, 68 insertions(+), 58 deletions(-)

diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index cda840f..939563c 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,61 @@ 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 spec doesn't give an explicit
+		   * behavior for conversion of float uniforms to
+		   * integer values, assume that the intention was to
+		   * behave like glGetIntegerv(), which does round to
+		   * 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++;
+	 }
       }
    }
 }
-- 
1.7.5.4



More information about the mesa-dev mailing list