/* * Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /** @file pack.c * * Tests packing of floating point values to GL_EXT_packed_float's * GL_UNSIGNED_INT_10F_11F_11F_REV format. */ #include "piglit-util-gl.h" PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 10; config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE; config.khr_no_error_support = PIGLIT_NO_ERRORS; PIGLIT_GL_TEST_CONFIG_END /* Any maximum e with m != 0 is NAN */ #define PACK(r, g, b) ((b << 22) | (g << 11) | (r)) #define GET_R(p) ((p) & 0x7ff) #define GET_G(p) (((p) >> 11) & 0x7ff) #define GET_B(p) (((p) >> 22) & 0x3ff) /* "An unsigned 11-bit floating-point number has no sign bit, a * 5-bit exponent (E), and a 6-bit mantissa (M). The value of an * unsigned 11-bit floating-point number (represented as an * 11-bit unsigned integer N) is determined by the following: * * 0.0, if E == 0 and M == 0, * 2^-14 * (M / 64), if E == 0 and M != 0, * 2^(E-15) * (1 + M/64), if 0 < E < 31, * INF, if E == 31 and M == 0, or * NaN, if E == 31 and M != 0, * * where * * E = floor(N / 64), and * M = N mod 64. * * Implementations are also allowed to use any of the following * alternative encodings: * * 0.0, if E == 0 and M != 0 * 2^(E-15) * (1 + M/64) if E == 31 and M == 0 * 2^(E-15) * (1 + M/64) if E == 31 and M != 0" */ #define F11(e, m) ((e) << 6 | (m)) /* "An unsigned 10-bit floating-point number has no sign bit, a * 5-bit exponent (E), and a 5-bit mantissa (M). The value of an * unsigned 10-bit floating-point number (represented as an * 10-bit unsigned integer N) is determined by the following: * * 0.0, if E == 0 and M == 0, * 2^-14 * (M / 32), if E == 0 and M != 0, * 2^(E-15) * (1 + M/32), if 0 < E < 31, * INF, if E == 31 and M == 0, or * NaN, if E == 31 and M != 0, * * where * * E = floor(N / 32), and * M = N mod 32." */ #define F10(e, m) ((e) << 5 | (m)) enum piglit_result piglit_display(void) { /* UNREACHED */ return PIGLIT_FAIL; } #define VALUE(r, g, b, p_r, p_g, p_b) { {r, g, b}, PACK(p_r, p_g, p_b) } struct { float in; uint32_t f10; uint32_t f11; } values[] = { { 1.0, F10(15, 0), F11(15, 0) }, { -1.0, F10(0, 0), F11(0, 0) }, /* "Likewise, finite positive values greater than 65024 * (the maximum finite representable unsigned 11-bit * floating-point value) are converted to 65024. * * ... * * Likewise, finite positive values greater than 64512 * (the maximum finite representable unsigned 10-bit * floating-point value) are converted to 64512" */ { 1000000, F10(30, 31), F11(30, 63) }, { 65025, F10(30, 31), F11(30, 63) }, { 64513, F10(30, 31), F11(30, 62) }, /* "Additionally: negative infinity is converted to zero; * positive infinity is converted to positive infinity; * and both positive and negative NaN are converted to * positive NaN." */ { INFINITY, F10(31, 0), F11(31, 0) }, { -INFINITY, F10(0, 0), F11(0, 0) }, { NAN, F10(31, 1), F11(31, 1) }, { -NAN, F10(31, 1), F11(31, 1) }, }; /* Per-pixel RGB float values. */ static float in[ARRAY_SIZE(values) * 3][3]; /* Per-pixel packed RGB float results */ static uint32_t out[ARRAY_SIZE(values) * 3]; /* Per-pixel packed RGB float values */ static uint32_t expected[ARRAY_SIZE(values) * 3]; static uint32_t * get_packed_values() { static float outf[ARRAY_SIZE(values) * 3][3]; GLuint tex; int i; /* Set up the texture data. */ for (i = 0; i < ARRAY_SIZE(values); i++) { in[i * 3 + 0][0] = values[i].in; in[i * 3 + 0][1] = 0.0; in[i * 3 + 0][2] = 0.0; in[i * 3 + 1][0] = 0.0; in[i * 3 + 1][1] = values[i].in; in[i * 3 + 1][2] = 0.0; in[i * 3 + 2][0] = 0.0; in[i * 3 + 2][1] = 0.0; in[i * 3 + 2][2] = values[i].in; expected[i * 3 + 0] = PACK(values[i].f11, 0, 0); expected[i * 3 + 1] = PACK(0, values[i].f11, 0); expected[i * 3 + 2] = PACK(0, 0, values[i].f10); } glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, ARRAY_SIZE(values) * 3, 0, GL_RGB, GL_FLOAT, in); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, out); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, outf); glDeleteTextures(1, &tex); return out; } static bool equals_11(uint32_t e, uint32_t o) { uint32_t e_exp = (e >> 6) & 0x1f; uint32_t e_man = e & 0x3f; uint32_t o_exp = (o >> 6) & 0x1f; uint32_t o_man = o & 0x3f; if (e_exp == 0) { /* Implementations are allowed to treat denorms as 0.0 */ return o_exp == 0; } else if (e_exp == 31) { if (e_man == 0) return o_exp == 31 && o_man == 0; else return o_exp == 31; } else { return e == o; } } static bool equals_10(uint32_t e, uint32_t o) { uint32_t e_exp = (e >> 5) & 0x1f; uint32_t e_man = e & 0x1f; uint32_t o_exp = (o >> 5) & 0x1f; uint32_t o_man = o & 0x1f; if (e_exp == 0) { /* Implementations are allowed to treat denorms as 0.0 */ return o_exp == 0; } else if (e_exp == 31) { if (e_man == 0) return o_exp == 31 && o_man == 0; else return o_exp == 31; } else { return e == o; } } static bool test_output() { bool pass = true; int i; for (i = 0; i < ARRAY_SIZE(values) * 3; i++) { uint32_t e_r = GET_R(expected[i]); uint32_t e_g = GET_G(expected[i]); uint32_t e_b = GET_B(expected[i]); uint32_t o_r = GET_R(out[i]); uint32_t o_g = GET_G(out[i]); uint32_t o_b = GET_B(out[i]); if (!equals_11(e_r, o_r) || !equals_11(e_g, o_g) || !equals_10(e_b, o_b)) { printf("Packed float value mismatch:\n"); printf(" input data: %f, %f, %f\n", in[i][0], in[i][1], in[i][2]); printf(" expected: 0x%08x (0x%03x, 0x%03x, 0x%03x)\n", expected[i], e_r, e_g, e_b); printf(" observed: 0x%08x (0x%03x, 0x%03x, 0x%03x)\n", out[i], o_r, o_g, o_b); } } return pass; } void piglit_init(int argc, char **argv) { bool pass = true; piglit_require_extension("GL_ARB_texture_float"); piglit_require_extension("GL_EXT_packed_float"); piglit_require_extension("GL_ARB_texture_non_power_of_two"); get_packed_values(); pass = test_output(); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }