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:
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);
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++;
+ }
}
}
}