<div dir="ltr">I've had this one kicking around my personal repo for a while.  It's nicer than the equivalent glean test (but doesn't cover quite as much) and is also useful for benchmarking texture uploads.<br>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Aug 22, 2014 at 1:00 PM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">---<br>
 tests/all.py                      |  29 ++<br>
 tests/texturing/CMakeLists.gl.txt |   1 +<br>
 tests/texturing/teximage-colors.c | 872 ++++++++++++++++++++++++++++++++++++++<br>
 3 files changed, 902 insertions(+)<br>
 create mode 100644 tests/texturing/teximage-colors.c<br>
<br>
diff --git a/tests/all.py b/tests/all.py<br>
index 17d5d9b..5670928 100644<br>
--- a/tests/all.py<br>
+++ b/tests/all.py<br>
@@ -797,6 +797,35 @@ add_concurrent_test(gl11, 'triangle-guardband-viewport')<br>
 add_concurrent_test(gl11, 'getteximage-targets 1D')<br>
 add_concurrent_test(gl11, 'getteximage-targets 2D')<br>
<br>
+color_formats = [<br>
+       'GL_RED', 'GL_R8', 'GL_R8_SNORM', 'GL_R16', 'GL_R16_SNORM',<br>
+       'GL_R16F', 'GL_R32F',<br>
+<br>
+       'GL_RG', 'GL_RG8', 'GL_RG8_SNORM', 'GL_RG16', 'GL_RG16_SNORM',<br>
+       'GL_RG16F', 'GL_RG32F',<br>
+<br>
+       'GL_RGB', 'GL_R3_G3_B2', 'GL_RGB4', 'GL_RGB5', 'GL_RGB8',<br>
+       'GL_RGB8_SNORM', 'GL_SRGB8', 'GL_RGB10', 'GL_R11F_G11F_B10F',<br>
+       'GL_RGB12', 'GL_RGB9_E5', 'GL_RGB16', 'GL_RGB16F',<br>
+       'GL_RGB16_SNORM', 'GL_RGB32F',<br>
+<br>
+       'GL_RGBA', 'GL_RGBA2', 'GL_RGBA4', 'GL_RGB5_A1', 'GL_RGBA8',<br>
+       'GL_RGB10_A2', 'GL_RGBA8_SNORM', 'GL_SRGB8_ALPHA8', 'GL_RGBA12',<br>
+       'GL_RGBA16', 'GL_RGBA16_SNORM', 'GL_RGBA32F',<br>
+<br>
+       'GL_ALPHA', 'GL_ALPHA4', 'GL_ALPHA8', 'GL_ALPHA12', 'GL_ALPHA16',<br>
+<br>
+       'GL_LUMINANCE', 'GL_LUMINANCE4', 'GL_LUMINANCE8', 'GL_SLUMINANCE8',<br>
+       'GL_LUMINANCE12', 'GL_LUMINANCE16',<br>
+<br>
+       'GL_LUMINANCE_ALPHA', 'GL_LUMINANCE4_ALPHA4',<br>
+       'GL_LUMINANCE6_ALPHA2', 'GL_LUMINANCE8_ALPHA8',<br>
+       'GL_SLUMINANCE8_ALPHA8', 'GL_LUMINANCE12_ALPHA4',<br>
+       'GL_LUMINANCE12_ALPHA12', 'GL_LUMINANCE16_ALPHA16',<br>
+]<br>
+for format in color_formats:<br>
+       add_concurrent_test(gl11, 'teximage-colors ' + format)<br>
+<br>
 gl10 = {}<br>
 spec['!OpenGL 1.0'] = gl10<br>
 add_concurrent_test(gl10, 'gl-1.0-beginend-coverage')<br>
diff --git a/tests/texturing/CMakeLists.gl.txt b/tests/texturing/CMakeLists.gl.txt<br>
index b121163..7d8d512 100644<br>
--- a/tests/texturing/CMakeLists.gl.txt<br>
+++ b/tests/texturing/CMakeLists.gl.txt<br>
@@ -87,5 +87,6 @@ ENDIF (UNIX)<br>
 piglit_add_executable (texsubimage texsubimage.c)<br>
 piglit_add_executable (texture-al texture-al.c)<br>
 piglit_add_executable (texture-rg texture-rg.c)<br>
+piglit_add_executable (teximage-colors teximage-colors.c)<br>
<br>
 # vim: ft=cmake:<br>
diff --git a/tests/texturing/teximage-colors.c b/tests/texturing/teximage-colors.c<br>
new file mode 100644<br>
index 0000000..c68bddd<br>
--- /dev/null<br>
+++ b/tests/texturing/teximage-colors.c<br>
@@ -0,0 +1,872 @@<br>
+/*<br>
+ * Copyright 2014 Intel Corporation<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include "piglit-util-gl-common.h"<br>
+<br>
+#define BENCHMARK_ITERATIONS 1000<br>
+<br>
+PIGLIT_GL_TEST_CONFIG_BEGIN<br>
+<br>
+       config.supports_gl_compat_version = 13;<br>
+<br>
+       config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;<br>
+<br>
+PIGLIT_GL_TEST_CONFIG_END<br>
+<br>
+struct texture_format {<br>
+       GLenum internal_format;<br>
+       const char *name;<br>
+       GLenum format;<br>
+       GLenum data_type;<br>
+};<br>
+<br>
+struct texture_format formats[] = {<br>
+#define FORMAT(IF, F, D) { IF, #IF, F, D }<br>
+       FORMAT(GL_RED, GL_RED, GL_NONE),<br>
+       FORMAT(GL_R8, GL_RED, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_R8_SNORM, GL_RED, GL_BYTE),<br>
+       FORMAT(GL_R16, GL_RED, GL_UNSIGNED_SHORT),<br>
+       FORMAT(GL_R16_SNORM, GL_RED, GL_SHORT),<br>
+       FORMAT(GL_R16F, GL_RED, GL_NONE),<br>
+       FORMAT(GL_R32F, GL_RED, GL_FLOAT),<br>
+<br>
+       FORMAT(GL_RG, GL_RG, GL_NONE),<br>
+       FORMAT(GL_RG8, GL_RG, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_RG8_SNORM, GL_RG, GL_BYTE),<br>
+       FORMAT(GL_RG16, GL_RG, GL_UNSIGNED_SHORT),<br>
+       FORMAT(GL_RG16_SNORM, GL_RG, GL_SHORT),<br>
+       FORMAT(GL_RG16F, GL_RG, GL_NONE),<br>
+       FORMAT(GL_RG32F, GL_RG, GL_FLOAT),<br>
+<br>
+       FORMAT(GL_RGB, GL_RGB, GL_NONE),<br>
+       FORMAT(GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_3_3_2),<br>
+       FORMAT(GL_RGB4, GL_RGB, GL_UNSIGNED_SHORT_5_6_5),<br>
+       FORMAT(GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_5_6_5),<br>
+       FORMAT(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_RGB8_SNORM, GL_RGB, GL_BYTE),<br>
+       FORMAT(GL_SRGB8, GL_RGB, GL_BYTE),<br>
+       FORMAT(GL_RGB10, GL_RGB, GL_UNSIGNED_SHORT),<br>
+       FORMAT(GL_R11F_G11F_B10F, GL_RGB, GL_NONE),<br>
+       FORMAT(GL_RGB12, GL_RGB, GL_UNSIGNED_SHORT),<br>
+       FORMAT(GL_RGB9_E5, GL_RGB, GL_NONE),<br>
+       FORMAT(GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT),<br>
+       FORMAT(GL_RGB16F, GL_RGB, GL_NONE),<br>
+       FORMAT(GL_RGB16_SNORM, GL_RGB, GL_SHORT),<br>
+       FORMAT(GL_RGB32F, GL_RGB, GL_FLOAT),<br>
+<br>
+       FORMAT(GL_RGBA, GL_RGBA, GL_NONE),<br>
+       FORMAT(GL_RGBA2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),<br>
+       FORMAT(GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),<br>
+       FORMAT(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1),<br>
+       FORMAT(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_10_10_10_2),<br>
+       FORMAT(GL_RGBA8_SNORM, GL_RGBA, GL_BYTE),<br>
+       FORMAT(GL_SRGB8_ALPHA8, GL_RGBA, GL_BYTE),<br>
+       FORMAT(GL_RGBA12, GL_RGBA, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT),<br>
+       FORMAT(GL_RGBA16_SNORM, GL_RGBA, GL_SHORT),<br>
+       FORMAT(GL_RGBA32F, GL_RGBA, GL_FLOAT),<br>
+<br>
+       FORMAT(GL_ALPHA, GL_ALPHA, GL_NONE),<br>
+       FORMAT(GL_ALPHA4, GL_ALPHA, GL_NONE),<br>
+       FORMAT(GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_ALPHA12, GL_ALPHA, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT),<br>
+<br>
+       FORMAT(GL_LUMINANCE, GL_LUMINANCE, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE4, GL_LUMINANCE, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_SLUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_LUMINANCE12, GL_LUMINANCE, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT),<br>
+<br>
+       FORMAT(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_ALPHA, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE),<br>
+       FORMAT(GL_LUMINANCE12_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE12_ALPHA12, GL_LUMINANCE_ALPHA, GL_NONE),<br>
+       FORMAT(GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT),<br>
+#undef FORMAT<br>
+};<br>
+<br>
+#define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof(*arr))<br>
+<br>
+static struct texture_format *<br>
+find_format(const char *name)<br>
+{<br>
+       int i;<br>
+<br>
+       for (i = 0; i < ARRAY_LENGTH(formats); ++i)<br>
+               if (strcmp(name, formats[i].name) == 0)<br>
+                       return &formats[i];<br>
+<br>
+       return NULL;<br>
+}<br>
+<br>
+static const GLenum gl_formats[] = {<br>
+       GL_RED,<br>
+       GL_GREEN,<br>
+       GL_BLUE,<br>
+       GL_ALPHA,<br>
+       GL_RG,<br>
+       GL_RGB,<br>
+       GL_BGR,<br>
+       GL_RGBA,<br>
+       GL_BGRA,<br>
+       GL_ABGR_EXT,<br>
+//     GL_INTENSITY,<br>
+       GL_LUMINANCE,<br>
+       GL_LUMINANCE_ALPHA,<br>
+};<br>
+<br>
+static const GLenum gl_types[] = {<br>
+       GL_UNSIGNED_BYTE_3_3_2,<br>
+       GL_UNSIGNED_BYTE_2_3_3_REV,<br>
+       GL_UNSIGNED_SHORT_5_6_5,<br>
+       GL_UNSIGNED_SHORT_5_6_5_REV,<br>
+       GL_UNSIGNED_SHORT_4_4_4_4,<br>
+       GL_UNSIGNED_SHORT_4_4_4_4_REV,<br>
+       GL_UNSIGNED_SHORT_5_5_5_1,<br>
+       GL_UNSIGNED_SHORT_1_5_5_5_REV,<br>
+       GL_UNSIGNED_INT_10_10_10_2,<br>
+       GL_UNSIGNED_INT_2_10_10_10_REV,<br>
+       GL_UNSIGNED_INT_8_8_8_8,<br>
+       GL_UNSIGNED_INT_8_8_8_8_REV,<br>
+       GL_BYTE,<br>
+       GL_UNSIGNED_BYTE,<br>
+       GL_SHORT,<br>
+       GL_UNSIGNED_SHORT,<br>
+       GL_FLOAT,<br>
+       GL_INT,<br>
+       GL_UNSIGNED_INT,<br>
+};<br>
+<br>
+static bool<br>
+valid_combination(GLenum format, GLenum type)<br>
+{<br>
+       switch (type) {<br>
+       case GL_UNSIGNED_BYTE_3_3_2:<br>
+       case GL_UNSIGNED_BYTE_2_3_3_REV:<br>
+       case GL_UNSIGNED_SHORT_5_6_5:<br>
+       case GL_UNSIGNED_SHORT_5_6_5_REV:<br>
+               return format == GL_RGB;<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4:<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4_REV:<br>
+       case GL_UNSIGNED_SHORT_5_5_5_1:<br>
+       case GL_UNSIGNED_SHORT_1_5_5_5_REV:<br>
+       case GL_UNSIGNED_INT_10_10_10_2:<br>
+       case GL_UNSIGNED_INT_2_10_10_10_REV:<br>
+       case GL_UNSIGNED_INT_8_8_8_8:<br>
+       case GL_UNSIGNED_INT_8_8_8_8_REV:<br>
+               return format == GL_RGBA || format == GL_BGRA;<br>
+       default:<br>
+               return true;<br>
+       }<br>
+}<br>
+<br>
+static float<br>
+un_to_float(unsigned char bits, unsigned int color)<br>
+{<br>
+       unsigned int max = ~(~0ul << bits);<br>
+       return (float)color / (float)max;<br>
+}<br>
+<br>
+static float<br>
+sn_to_float(unsigned char bits, int color)<br>
+{<br>
+       int max = ~(~0 << (bits-1));<br>
+       if (color < -max)<br>
+               color = -max;<br>
+       return (float)color / (float)max;<br>
+}<br>
+<br>
+static float<br>
+srgb_to_linear(float s)<br>
+{<br>
+       if (s > 0.0405)<br>
+               return pow((s + 0.055) / 1.055, 2.4);<br>
+       else<br>
+               return s / 12.92;<br>
+}<br>
+<br>
+#define UNPACK(val, len, off) ((val) >> off) & ~(~0ul << len)<br>
+<br>
+static void<br>
+to_float(void *data, int num_chan, GLenum type, float *out)<br>
+{<br>
+       int i;<br>
+<br>
+       switch (type) {<br>
+       case GL_UNSIGNED_BYTE_3_3_2:<br>
+               assert(num_chan == 3);<br>
+               out[0] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 5));<br>
+               out[1] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 2));<br>
+               out[2] = un_to_float(2, UNPACK(*(GLubyte *)data, 2, 0));<br>
+               break;<br>
+       case GL_UNSIGNED_BYTE_2_3_3_REV:<br>
+               assert(num_chan == 3);<br>
+               out[0] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 0));<br>
+               out[1] = un_to_float(3, UNPACK(*(GLubyte *)data, 3, 3));<br>
+               out[2] = un_to_float(2, UNPACK(*(GLubyte *)data, 2, 6));<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_5_6_5:<br>
+               assert(num_chan == 3);<br>
+               out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));<br>
+               out[1] = un_to_float(6, UNPACK(*(GLushort *)data, 6, 5));<br>
+               out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_5_6_5_REV:<br>
+               assert(num_chan == 3);<br>
+               out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));<br>
+               out[1] = un_to_float(6, UNPACK(*(GLushort *)data, 6, 5));<br>
+               out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 12));<br>
+               out[1] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 8));<br>
+               out[2] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 4));<br>
+               out[3] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 0));<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4_REV:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 0));<br>
+               out[1] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 4));<br>
+               out[2] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 8));<br>
+               out[3] = un_to_float(4, UNPACK(*(GLushort *)data, 4, 12));<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_5_5_5_1:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 11));<br>
+               out[1] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 6));<br>
+               out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 1));<br>
+               out[3] = un_to_float(1, UNPACK(*(GLushort *)data, 1, 0));<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_1_5_5_5_REV:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 0));<br>
+               out[1] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 5));<br>
+               out[2] = un_to_float(5, UNPACK(*(GLushort *)data, 5, 10));<br>
+               out[3] = un_to_float(1, UNPACK(*(GLushort *)data, 1, 15));<br>
+               break;<br>
+       case GL_UNSIGNED_INT_10_10_10_2:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 22));<br>
+               out[1] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 12));<br>
+               out[2] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 2));<br>
+               out[3] = un_to_float(2, UNPACK(*(GLuint *)data, 2, 0));<br>
+               break;<br>
+       case GL_UNSIGNED_INT_2_10_10_10_REV:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 0));<br>
+               out[1] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 10));<br>
+               out[2] = un_to_float(10, UNPACK(*(GLuint *)data, 10, 20));<br>
+               out[3] = un_to_float(2, UNPACK(*(GLuint *)data, 2, 30));<br>
+               break;<br>
+       case GL_UNSIGNED_INT_8_8_8_8:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 24));<br>
+               out[1] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 16));<br>
+               out[2] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 8));<br>
+               out[3] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 0));<br>
+               break;<br>
+       case GL_UNSIGNED_INT_8_8_8_8_REV:<br>
+               assert(num_chan == 4);<br>
+               out[0] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 0));<br>
+               out[1] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 8));<br>
+               out[2] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 16));<br>
+               out[3] = un_to_float(8, UNPACK(*(GLuint *)data, 8, 24));<br>
+               break;<br>
+       case GL_BYTE:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = sn_to_float(8, ((GLbyte *)data)[i]);<br>
+               break;<br>
+       case GL_UNSIGNED_BYTE:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = un_to_float(8, ((GLubyte *)data)[i]);<br>
+               break;<br>
+       case GL_SHORT:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = sn_to_float(16, ((GLshort *)data)[i]);<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = un_to_float(16, ((GLushort *)data)[i]);<br>
+               break;<br>
+       case GL_FLOAT:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = ((float *)data)[i];<br>
+               break;<br>
+       case GL_INT:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = sn_to_float(32, ((GLint *)data)[i]);<br>
+               break;<br>
+       case GL_UNSIGNED_INT:<br>
+               for (i = 0; i < num_chan; ++i)<br>
+                       out[i] = un_to_float(32, ((GLuint *)data)[i]);<br>
+               break;<br>
+       default:<br>
+               assert(!"Invalid type");<br>
+       }<br>
+}<br>
+<br>
+static bool<br>
+is_format_signed(GLenum format)<br>
+{<br>
+       switch (format) {<br>
+       case GL_R8_SNORM:<br>
+       case GL_R16_SNORM:<br>
+       case GL_R32F:<br>
+       case GL_RG8_SNORM:<br>
+       case GL_RG16_SNORM:<br>
+       case GL_RG32F:<br>
+       case GL_RGB8_SNORM:<br>
+       case GL_RGB16_SNORM:<br>
+       case GL_RGB32F:<br>
+       case GL_RGBA8_SNORM:<br>
+       case GL_RGBA16_SNORM:<br>
+       case GL_RGBA32F:<br>
+               return true;<br>
+       default:<br>
+               return false;<br>
+       }<br>
+}<br>
+<br>
+static bool<br>
+is_format_srgb(GLenum format)<br>
+{<br>
+       switch (format) {<br>
+       case GL_SRGB:<br>
+       case GL_SRGB8:<br>
+       case GL_SRGB_ALPHA:<br>
+       case GL_SRGB8_ALPHA8:<br>
+       case GL_SLUMINANCE:<br>
+       case GL_SLUMINANCE8:<br>
+       case GL_SLUMINANCE_ALPHA:<br>
+       case GL_SLUMINANCE8_ALPHA8:<br>
+               return true;<br>
+       default:<br>
+               return false;<br>
+       }<br>
+}<br>
+<br>
+static int<br>
+num_channels(GLenum format)<br>
+{<br>
+       switch (format) {<br>
+       case GL_RED:<br>
+       case GL_GREEN:<br>
+       case GL_BLUE:<br>
+       case GL_ALPHA:<br>
+       case GL_INTENSITY:<br>
+       case GL_LUMINANCE:<br>
+               return 1;<br>
+       case GL_RG:<br>
+       case GL_LUMINANCE_ALPHA:<br>
+               return 2;<br>
+       case GL_RGB:<br>
+       case GL_BGR:<br>
+               return 3;<br>
+       case GL_RGBA:<br>
+       case GL_BGRA:<br>
+       case GL_ABGR_EXT:<br>
+               return 4;<br>
+       default:<br>
+               assert(!"Invalid format");<br>
+               return 0;<br>
+       }<br>
+}<br>
+<br>
+static int<br>
+bytes_per_pixel(GLenum format, GLenum type)<br>
+{<br>
+       int channels = num_channels(format);<br>
+<br>
+       switch (type) {<br>
+       case GL_UNSIGNED_BYTE_3_3_2:<br>
+       case GL_UNSIGNED_BYTE_2_3_3_REV:<br>
+               assert(channels == 3);<br>
+               return 1;<br>
+       case GL_UNSIGNED_SHORT_5_6_5:<br>
+       case GL_UNSIGNED_SHORT_5_6_5_REV:<br>
+               assert(channels == 3);<br>
+               return 2;<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4:<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4_REV:<br>
+       case GL_UNSIGNED_SHORT_5_5_5_1:<br>
+       case GL_UNSIGNED_SHORT_1_5_5_5_REV:<br>
+               assert(channels == 4);<br>
+               return 2;<br>
+       case GL_UNSIGNED_INT_10_10_10_2:<br>
+       case GL_UNSIGNED_INT_2_10_10_10_REV:<br>
+       case GL_UNSIGNED_INT_8_8_8_8:<br>
+       case GL_UNSIGNED_INT_8_8_8_8_REV:<br>
+               assert(channels == 4);<br>
+               return 4;<br>
+       case GL_BYTE:<br>
+       case GL_UNSIGNED_BYTE:<br>
+               return channels;<br>
+       case GL_SHORT:<br>
+       case GL_UNSIGNED_SHORT:<br>
+               return channels * 2;<br>
+       case GL_FLOAT:<br>
+       case GL_INT:<br>
+       case GL_UNSIGNED_INT:<br>
+               return channels * 4;<br>
+       default:<br>
+               assert(!"Invalid type");<br>
+               return 0;<br>
+       }<br>
+}<br>
+<br>
+static const char *frag_shader_unsigned_src =<br>
+"uniform sampler2D tex; \n"<br>
+"void main() \n"<br>
+"{ \n"<br>
+"      gl_FragColor = texture2D(tex, gl_TexCoord[0].xy);\n"<br>
+"} \n";<br>
+<br>
+static const char *frag_shader_signed_src =<br>
+"uniform sampler2D tex; \n"<br>
+"void main() \n"<br>
+"{ \n"<br>
+"      gl_FragColor = 0.5 + 0.5 * texture2D(tex, gl_TexCoord[0].xy);\n"<br>
+"} \n";<br>
+<br>
+int texture_size = 31;<br>
+struct texture_format *format = NULL;<br>
+GLuint unsigned_prog, signed_prog;<br>
+void *rand_data;<br>
+float tolerance[4];<br>
+bool benchmark = false;<br>
+<br>
+void<br>
+piglit_init(int argc, char **argv)<br>
+{<br>
+       int i, seed = 0;<br>
+<br>
+       for (i = 1; i < argc; ++i) {<br>
+               if (sscanf(argv[i], "--seed=%d", &seed) > 0) {<br>
+                       srand(seed);<br>
+               } else if (strcmp(argv[i], "--benchmark") == 0) {<br>
+                       benchmark = true;<br>
+                       texture_size = 128;<br>
+               } else if (i == argc - 1) {<br>
+                       format = find_format(argv[i]);<br>
+                       break;<br>
+               }<br>
+       }<br>
+<br>
+       if (argc < 1) {<br>
+               printf("usage: texstore-colors [--seed=seed] [--benchmark] format");<br>
+               exit(1);<br>
+       }<br>
+<br>
+       piglit_require_extension("GL_EXT_texture_integer");<br>
+<br>
+       assert(format);<br>
+<br>
+       signed_prog = piglit_build_simple_program(NULL, frag_shader_signed_src);<br>
+       unsigned_prog = piglit_build_simple_program(NULL, frag_shader_unsigned_src);<br>
+<br>
+       srand(seed);<br>
+       rand_data = malloc(texture_size * texture_size * 128);<br>
+       for (i = 0; i < texture_size * texture_size * 128; ++i)<br>
+               ((GLubyte *)rand_data)[i] = rand();<br>
+<br>
+       if (is_format_srgb(format->internal_format)) {<br>
+               /* We loose a little precision in the high numbers */<br>
+               tolerance[0] = 0.02;<br>
+               tolerance[1] = 0.02;<br>
+               tolerance[2] = 0.02;<br>
+               tolerance[3] = 0.02;<br>
+       } else {<br>
+               tolerance[0] = 0.01;<br>
+               tolerance[1] = 0.01;<br>
+               tolerance[2] = 0.01;<br>
+               tolerance[3] = 0.01;<br>
+       }<br>
+<br>
+       if (format->internal_format == GL_R11F_G11F_B10F) {<br>
+               tolerance[0] = 0.3;<br>
+               tolerance[1] = 0.3;<br>
+               tolerance[2] = 0.3;<br>
+       }<br>
+<br>
+       switch (format->data_type) {<br>
+       case GL_UNSIGNED_BYTE_3_3_2:<br>
+       case GL_UNSIGNED_BYTE_2_3_3_REV:<br>
+               tolerance[0] = 0.3;<br>
+               tolerance[1] = 0.3;<br>
+               tolerance[2] = 0.3;<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_5_5_5_1:<br>
+       case GL_UNSIGNED_SHORT_1_5_5_5_REV:<br>
+               tolerance[3] = 0.6;<br>
+       case GL_UNSIGNED_SHORT_5_6_5:<br>
+       case GL_UNSIGNED_SHORT_5_6_5_REV:<br>
+               tolerance[0] = 0.05;<br>
+               tolerance[1] = 0.05;<br>
+               tolerance[2] = 0.05;<br>
+               break;<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4:<br>
+       case GL_UNSIGNED_SHORT_4_4_4_4_REV:<br>
+               tolerance[0] = 0.1;<br>
+               tolerance[1] = 0.1;<br>
+               tolerance[2] = 0.1;<br>
+               tolerance[3] = 0.1;<br>
+               break;<br>
+       case GL_UNSIGNED_INT_10_10_10_2:<br>
+       case GL_UNSIGNED_INT_2_10_10_10_REV:<br>
+               tolerance[3] = 0.3;<br>
+               break;<br>
+       }<br>
+}<br>
+<br>
+void<br>
+to_expected(GLenum test_format, GLenum test_type, void *up_raw, float *expected)<br>
+{<br>
+       float up_rgba[4];<br>
+       int num_chan = num_channels(test_format);<br>
+<br>
+       to_float(up_raw, num_chan, test_type, up_rgba);<br>
+<br>
+       expected[0] = 0.0f;<br>
+       expected[1] = 0.0f;<br>
+       expected[2] = 0.0f;<br>
+       expected[3] = 1.0f;<br>
+<br>
+       switch (test_format) {<br>
+       case GL_RED:<br>
+               expected[0] = up_rgba[0];<br>
+               break;<br>
+       case GL_GREEN:<br>
+               expected[1] = up_rgba[0];<br>
+               break;<br>
+       case GL_BLUE:<br>
+               expected[2] = up_rgba[0];<br>
+               break;<br>
+       case GL_ALPHA:<br>
+               expected[3] = up_rgba[0];<br>
+               break;<br>
+       case GL_RG:<br>
+               expected[0] = up_rgba[0];<br>
+               expected[1] = up_rgba[1];<br>
+               break;<br>
+       case GL_RGBA:<br>
+               expected[3] = up_rgba[3];<br>
+       case GL_RGB:<br>
+               expected[0] = up_rgba[0];<br>
+               expected[1] = up_rgba[1];<br>
+               expected[2] = up_rgba[2];<br>
+               break;<br>
+       case GL_BGRA:<br>
+               expected[3] = up_rgba[3];<br>
+       case GL_BGR:<br>
+               expected[0] = up_rgba[2];<br>
+               expected[1] = up_rgba[1];<br>
+               expected[2] = up_rgba[0];<br>
+               break;<br>
+       case GL_ABGR_EXT:<br>
+               expected[0] = up_rgba[3];<br>
+               expected[1] = up_rgba[2];<br>
+               expected[2] = up_rgba[1];<br>
+               expected[3] = up_rgba[0];<br>
+               break;<br>
+       case GL_INTENSITY:<br>
+               expected[0] = up_rgba[0];<br>
+               expected[1] = up_rgba[0];<br>
+               expected[2] = up_rgba[0];<br>
+               expected[3] = up_rgba[0];<br>
+               break;<br>
+       case GL_LUMINANCE_ALPHA:<br>
+               expected[3] = up_rgba[1];<br>
+       case GL_LUMINANCE:<br>
+               expected[0] = up_rgba[0];<br>
+               expected[1] = up_rgba[0];<br>
+               expected[2] = up_rgba[0];<br>
+               break;<br>
+       default:<br>
+               assert(!"Invalid color format");<br>
+       }<br>
+<br>
+       switch (format->format) {<br>
+       case GL_RED:<br>
+       case GL_RED_INTEGER:<br>
+               expected[1] = 0.0f;<br>
+       case GL_RG:<br>
+       case GL_RG_INTEGER:<br>
+               expected[2] = 0.0f;<br>
+       case GL_RGB:<br>
+       case GL_RGB_INTEGER:<br>
+               expected[3] = 1.0f;<br>
+               break;<br>
+       case GL_RGBA:<br>
+       case GL_RGBA_INTEGER:<br>
+               break;<br>
+       case GL_ALPHA:<br>
+               expected[0] = 0.0f;<br>
+               expected[1] = 0.0f;<br>
+               expected[2] = 0.0f;<br>
+               break;<br>
+       case GL_LUMINANCE:<br>
+               expected[3] = 1.0f;<br>
+       case GL_LUMINANCE_ALPHA:<br>
+               expected[0] = expected[0];<br>
+               expected[1] = expected[0];<br>
+               expected[2] = expected[0];<br>
+               break;<br>
+       default:<br>
+               assert(!"Invalid color format");<br>
+       }<br>
+<br>
+       if (!is_format_signed(format->internal_format)) {<br>
+               if (expected[0] < 0.0f)<br>
+                       expected[0] = 0.0f;<br>
+               if (expected[1] < 0.0f)<br>
+                       expected[1] = 0.0f;<br>
+               if (expected[2] < 0.0f)<br>
+                       expected[2] = 0.0f;<br>
+               if (expected[3] < 0.0f)<br>
+                       expected[3] = 0.0f;<br>
+       }<br>
+<br>
+       if (is_format_srgb(format->internal_format)) {<br>
+               expected[0] = srgb_to_linear(expected[0]);<br>
+               expected[1] = srgb_to_linear(expected[1]);<br>
+               expected[2] = srgb_to_linear(expected[2]);<br>
+       }<br>
+}<br>
+<br>
+enum piglit_result<br>
+run_test(GLenum test_format, GLenum test_type, float *time_out)<br>
+{<br>
+       bool pass = true;<br>
+       int64_t time;<br>
+       GLuint tex;<br>
+       int i, Bpp, channels;<br>
+       float *tmp, *expected, *observed;<br>
+       void *data;<br>
+<br>
+       glGenTextures(1, &tex);<br>
+       glBindTexture(GL_TEXTURE_2D, tex);<br>
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);<br>
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);<br>
+<br>
+       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);<br>
+<br>
+       channels = num_channels(test_format);<br>
+       Bpp = bytes_per_pixel(test_format, test_type);<br>
+<br>
+       if (test_type == GL_FLOAT) {<br>
+               /* Sanatize so we don't get invalid floating point values */<br>
+               tmp = malloc(texture_size * texture_size * channels * sizeof(float));<br>
+               for (i = 0; i < texture_size * texture_size * channels; ++i)<br>
+                       tmp[i] = sn_to_float(32, ((GLint *)rand_data)[i]);<br>
+               data = tmp;<br>
+       } else {<br>
+               tmp = NULL;<br>
+               data = rand_data;<br>
+       }<br>
+<br>
+       expected = malloc(texture_size * texture_size * 4 * sizeof(float));<br>
+       for (i = 0; i < texture_size * texture_size; ++i)<br>
+               to_expected(test_format, test_type, (GLubyte *)data + (i * Bpp),<br>
+                           expected + 4 * i);<br>
+<br>
+       if (benchmark) {<br>
+               time = piglit_get_microseconds();<br>
+               for (i = 0; i < BENCHMARK_ITERATIONS; ++i)<br>
+                       glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,<br>
+                                    texture_size, texture_size, 0,<br>
+                                    test_format, test_type, data);<br>
+               time = piglit_get_microseconds() - time;<br>
+               *time_out = (double)time / (double)BENCHMARK_ITERATIONS;<br>
+       } else {<br>
+               glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,<br>
+                            texture_size, texture_size, 0,<br>
+                            test_format, test_type, data);<br>
+       }<br>
+       pass &= piglit_check_gl_error(GL_NO_ERROR);<br>
+<br>
+       if (is_format_signed(format->internal_format)) {<br>
+               glUseProgram(signed_prog);<br>
+<br>
+               for (i = 0; i < texture_size * texture_size * 4; ++i)<br>
+                       expected[i] = 0.5 + 0.5 * expected[i];<br>
+       } else {<br>
+               glUseProgram(unsigned_prog);<br>
+       }<br>
+<br>
+       piglit_draw_rect_tex(0, 0, texture_size, texture_size, 0, 0, 1, 1);<br>
+<br>
+       observed = malloc(texture_size * texture_size * 4 * sizeof(float));<br>
+       glReadPixels(0, 0, texture_size, texture_size,<br>
+                    GL_RGBA, GL_FLOAT, observed);<br>
+       pass &= piglit_check_gl_error(GL_NO_ERROR);<br>
+<br>
+       pass &= piglit_compare_images_color(0, 0, texture_size, texture_size, 4,<br>
+                                           tolerance, expected, observed);<br>
+<br>
+       free(observed);<br>
+       free(expected);<br>
+       free(tmp);<br>
+<br>
+       piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,<br>
+                                    "%s texture with %s and %s",<br>
+                                    piglit_get_gl_enum_name(format->internal_format),<br>
+                                    piglit_get_gl_enum_name(test_format),<br>
+                                    piglit_get_gl_enum_name(test_type));<br>
+<br>
+       glDeleteTextures(1, &tex);<br>
+<br>
+       return pass;<br>
+}<br>
+<br>
+bool<br>
+test_exact()<br>
+{<br>
+       int i, Bpp, channels;<br>
+       float *tmp_float;<br>
+       GLubyte *data, *observed;<br>
+       GLint tex_width, tex_height;<br>
+       bool pass = true;<br>
+<br>
+       if (format->data_type == GL_NONE) {<br>
+               piglit_report_subtest_result(PIGLIT_SKIP,<br>
+                                            "Exact upload-download of %s",<br>
+                                            piglit_get_gl_enum_name(format->internal_format));<br>
+               return true;<br>
+       }<br>
+<br>
+       channels = num_channels(format->format);<br>
+       Bpp = bytes_per_pixel(format->format, format->data_type);<br>
+<br>
+       if (format->data_type == GL_FLOAT) {<br>
+               /* Sanatize so we don't get invalid floating point values */<br>
+               tmp_float = malloc(texture_size * texture_size *<br>
+                                  channels * sizeof(float));<br>
+               for (i = 0; i < texture_size * texture_size * channels; ++i)<br>
+                       tmp_float[i] = sn_to_float(32, ((GLint *)rand_data)[i]);<br>
+               data = (GLubyte *)tmp_float;<br>
+       } else {<br>
+               tmp_float = NULL;<br>
+               data = rand_data;<br>
+       }<br>
+<br>
+       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);<br>
+       glTexImage2D(GL_TEXTURE_2D, 0, format->internal_format,<br>
+                    texture_size, texture_size, 0, format->format,<br>
+                    format->data_type, data);<br>
+       pass &= piglit_check_gl_error(GL_NO_ERROR);<br>
+<br>
+       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_width);<br>
+       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_height);<br>
+       glPixelStorei(GL_PACK_ALIGNMENT, 1);<br>
+       observed = malloc(tex_width * tex_height * Bpp);<br>
+<br>
+       glGetTexImage(GL_TEXTURE_2D, 0, format->format, format->data_type,<br>
+                     observed);<br>
+       pass &= piglit_check_gl_error(GL_NO_ERROR);<br>
+<br>
+       for (i = 0; i < texture_size; ++i)<br>
+               pass &= memcmp(&data[i * texture_size * Bpp],<br>
+                              &observed[i * tex_width * Bpp],<br>
+                              texture_size * Bpp) == 0;<br>
+<br>
+       free(observed);<br>
+       free(tmp_float);<br>
+<br>
+       piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,<br>
+                                    "Exact upload-download of %s",<br>
+                                    piglit_get_gl_enum_name(format->internal_format));<br>
+<br>
+       return pass;<br>
+}<br>
+<br>
+enum piglit_result<br>
+piglit_display(void)<br>
+{<br>
+       bool warn = false, pass = true;<br>
+       GLuint rb, fbo;<br>
+       int i, j;<br>
+       float times[ARRAY_LENGTH(gl_formats)][ARRAY_LENGTH(gl_types)];<br>
+<br>
+       glGenRenderbuffersEXT(1, &rb);<br>
+       glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb);<br>
+       glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,<br>
+                                GL_RGBA, texture_size, texture_size);<br>
+       pass &= piglit_check_gl_error(GL_NO_ERROR);<br>
+<br>
+       glGenFramebuffersEXT(1, &fbo);<br>
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);<br>
+       glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,<br>
+                                    GL_COLOR_ATTACHMENT0_EXT,<br>
+                                    GL_RENDERBUFFER_EXT, rb);<br>
+       pass &= piglit_check_gl_error(GL_NO_ERROR);<br>
+<br>
+       /* Set up basic GL stuff */<br>
+       glEnable(GL_TEXTURE_2D);<br>
+       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);<br>
+       piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);<br>
+<br>
+       warn = !test_exact();<br>
+<br>
+       for (i = 0; i < ARRAY_LENGTH(gl_formats); ++i) {<br>
+               for (j = 0; j < ARRAY_LENGTH(gl_types); ++j) {<br>
+                       if (!valid_combination(gl_formats[i], gl_types[j]))<br>
+                               continue;<br>
+<br>
+                       pass &= run_test(gl_formats[i], gl_types[j],<br>
+                                        &times[i][j]);<br>
+               }<br>
+       }<br>
+<br>
+       glDisable(GL_TEXTURE_2D);<br>
+       glDeleteFramebuffers(1, &fbo);<br>
+       glDeleteRenderbuffers(1, &rb);<br>
+<br>
+       if (benchmark) {<br>
+               fprintf(stdout, "internalFormat, format, type, time (us/call)\n");<br>
+               for (i = 0; i < ARRAY_LENGTH(gl_formats); ++i) {<br>
+                       for (j = 0; j < ARRAY_LENGTH(gl_types); ++j) {<br>
+                               if (!valid_combination(gl_formats[i], gl_types[j]))<br>
+                                       continue;<br>
+<br>
+                               fprintf(stdout, "%s, %s, %s, %.3f\n",<br>
+                                       piglit_get_gl_enum_name(format->internal_format),<br>
+                                       piglit_get_gl_enum_name(gl_formats[i]),<br>
+                                       piglit_get_gl_enum_name(gl_types[j]),<br>
+                                       times[i][j]);<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
+       if (pass) {<br>
+               return warn ? PIGLIT_WARN : PIGLIT_PASS;<br>
+       } else {<br>
+               return PIGLIT_FAIL;<br>
+       }<br>
+}<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.1.0<br>
<br>
</font></span></blockquote></div><br></div>