- union gl_constant_value *const dst =
- (union gl_constant_value *) paramsOut;
-
- /* This code could be optimized by putting the loop inside the switch
- * statements. However, this is not expected to be
- * performance-critical code.
- */
- for (unsigned i = 0; i < elements; i++) {
- switch (returnType) {
- case GLSL_TYPE_FLOAT:
- switch (uni->type->base_type) {
- case GLSL_TYPE_UINT:
- dst[i].f = (float) src[i].u;
- break;
- case GLSL_TYPE_INT:
- case GLSL_TYPE_SAMPLER:
- dst[i].f = (float) src[i].i;
- break;
- case GLSL_TYPE_BOOL:
- dst[i].f = src[i].i ? 1.0f : 0.0f;
- break;
- default:
- assert(!"Should not get here.");
- break;
- }
- break;
-
- case GLSL_TYPE_INT:
- case GLSL_TYPE_UINT:
- switch (uni->type->base_type) {
- case GLSL_TYPE_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..."
- */
- dst[i].i = IROUND(src[i].f);
- break;
- case GLSL_TYPE_BOOL:
- dst[i].i = src[i].i ? 1 : 0;
- break;
- default:
- assert(!"Should not get here.");
- break;
- }
- break;
-
- default:
- assert(!"Should not get here.");
- break;
- }
- }
+ union gl_constant_value *const dst =
+ (union gl_constant_value *) paramsOut;
+ /* This code could be optimized by putting the loop inside the switch
+ * statements. However, this is not expected to be
+ * performance-critical code.
+ */
+ for (unsigned i = 0; i < elements; i++) {
+ int sidx = i * dmul;
+ int didx = i * rmul;
+
+ switch (returnType) {
+ case GLSL_TYPE_FLOAT:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_UINT:
+ dst[didx].f = (float) src[sidx].u;
+ break;
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
+ dst[didx].f = (float) src[sidx].i;
+ break;
+ case GLSL_TYPE_BOOL:
+ dst[didx].f = src[sidx].i ? 1.0f : 0.0f;
+ break;
+ case GLSL_TYPE_DOUBLE: {
+ double tmp;
+ memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+ dst[didx].f = tmp;
+ break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+ dst[didx].f = tmp;
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].i, sizeof(tmp));
+ dst[didx].f = tmp;
+ break;
+ }
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
+
+ case GLSL_TYPE_DOUBLE:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_UINT: {
+ double tmp = src[sidx].u;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE: {
+ double tmp = src[sidx].i;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_BOOL: {
+ double tmp = src[sidx].i ? 1.0 : 0.0;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_FLOAT: {
+ double tmp = src[sidx].f;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmpu;
+ double tmp;
+ memcpy(&tmpu, &src[sidx].u, sizeof(tmpu));
+ tmp = tmpu;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ int64_t tmpi;
+ double tmp;
+ memcpy(&tmpi, &src[sidx].i, sizeof(tmpi));
+ tmp = tmpi;
+ memcpy(&dst[didx].f, &tmp, sizeof(tmp));
+ break;
+ }
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
+
+ case GLSL_TYPE_INT:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_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..."
+ */
+ dst[didx].i = (int64_t) roundf(src[sidx].f);
+ break;
+ case GLSL_TYPE_BOOL:
+ dst[didx].i = src[sidx].i ? 1 : 0;
+ break;
+ case GLSL_TYPE_UINT:
+ dst[didx].i = MIN2(src[sidx].i, INT_MAX);
+ break;
+ case GLSL_TYPE_DOUBLE: {
+ double tmp;
+ memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+ dst[didx].i = (int64_t) round(tmp);
+ break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+ dst[didx].i = tmp;
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ int64_t tmp;
+ memcpy(&tmp, &src[sidx].i, sizeof(tmp));
+ dst[didx].i = tmp;
+ break;
+ }
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
+
+ case GLSL_TYPE_UINT:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_FLOAT:
+ /* The spec isn't terribly clear how to handle negative
+ * values with an unsigned return type.
+ *
+ * GL 4.5 section 2.2.2 ("Data Conversions for State
+ * Query Commands") says:
+ *
+ * "If a value is so large in magnitude that it cannot be
+ * represented by the returned data type, then the nearest
+ * value representable using the requested type is
+ * returned."
+ */
+ dst[didx].u = src[sidx].f < 0.0f ?
+ 0u : (uint32_t) roundf(src[sidx].f);
+ break;
+ case GLSL_TYPE_BOOL:
+ dst[didx].i = src[sidx].i ? 1 : 0;
+ break;
+ case GLSL_TYPE_INT:
+ dst[didx].i = MAX2(src[sidx].i, 0);
+ break;
+ case GLSL_TYPE_DOUBLE: {
+ double tmp;
+ memcpy(&tmp, &src[sidx].f, sizeof(tmp));
+ dst[didx].u = tmp < 0.0 ? 0u : (uint32_t) round(tmp);
+ break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t tmp;
+ memcpy(&tmp, &src[sidx].u, sizeof(tmp));
+ dst[didx].i = MIN2(tmp, INT_MAX);
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ int64_t tmp;
+ memcpy(&tmp, &src[sidx].i, sizeof(tmp));
+ dst[didx].i = MAX2(tmp, 0);
+ break;
+ }
+ default:
+ unreachable("invalid uniform type");
+ }
+ break;
+
+ case GLSL_TYPE_INT64:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_UINT: {
+ uint64_t tmp = src[sidx].u;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE: {
+ int64_t tmp = src[sidx].i;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_BOOL: {
+ int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_UINT64: {
+ uint64_t u64;
+ memcpy(&u64, &src[sidx].u, sizeof(u64));
+ int64_t tmp = MIN2(u64, INT_MAX);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_FLOAT: {
+ int64_t tmp = (int64_t) roundf(src[sidx].f);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_DOUBLE: {
+ double d;
+ memcpy(&d, &src[sidx].f, sizeof(d));
+ int64_t tmp = (int64_t) round(d);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
+
+ case GLSL_TYPE_UINT64:
+ switch (uni->type->base_type) {
+ case GLSL_TYPE_UINT: {
+ uint64_t tmp = src[sidx].u;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE: {
+ int64_t tmp = MAX2(src[sidx].i, 0);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_BOOL: {
+ int64_t tmp = src[sidx].i ? 1.0f : 0.0f;
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_INT64: {
+ uint64_t i64;
+ memcpy(&i64, &src[sidx].i, sizeof(i64));
+ uint64_t tmp = MAX2(i64, 0);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_FLOAT: {
+ uint64_t tmp = src[sidx].f < 0.0f ?
+ 0ull : (uint64_t) roundf(src[sidx].f);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ case GLSL_TYPE_DOUBLE: {
+ double d;
+ memcpy(&d, &src[sidx].f, sizeof(d));
+ uint64_t tmp = (d < 0.0) ? 0ull : (uint64_t) round(d);
+ memcpy(&dst[didx].u, &tmp, sizeof(tmp));
+ break;
+ }
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ break;
+
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ }