Mesa (master): mesa: Fix glGetUniform() type conversions.

Eric Anholt anholt at kemper.freedesktop.org
Tue Aug 30 12:10:33 PDT 2011


Module: Mesa
Branch: master
Commit: 9fa41f0742b7486e462e088a66bef8cebdf114f5
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9fa41f0742b7486e462e088a66bef8cebdf114f5

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Aug 23 13:46:12 2011 -0700

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 <kenneth at whitecape.org>
Acked-by: Ian Romanick <ian.d.romanick at intel.com>

---

 src/mesa/main/uniforms.c |  137 ++++++++++++++++++++++++++-------------------
 1 files changed, 79 insertions(+), 58 deletions(-)

diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index cda840f..fe1ce6d 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++;
+	 }
       }
    }
 }



More information about the mesa-commit mailing list