summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2010-08-26 16:52:31 +0200
committerMarek Olšák <maraeo@gmail.com>2010-08-30 06:21:38 +0200
commit15141eebd19803244c4b3928fe8fded277732598 (patch)
tree0c773cbcccb2e01fd3bad19548b991da5b4a77b7
parentcd3167f1afadad9f1d07113d1a55bc3a2fa143dd (diff)
New testsuite for ARB_color_buffer_float (v2)
This in an updated version of the test I posted, now split into 8 tests sharing a common header file. It now features testing of multiple render targets and fog. Test output logs and results on GeForce 8xxx, GTX 2xx or ideally GTX 4xx with the proprietary drivers would be really welcome. The files are put in "spec/arb_color_buffer_float" with the idea of starting a convention of writing testsuites for each new extension to be implemented in Mesa, putting it in "spec/<extension_name>". The tests now fail on any bugs in the default mode. If "-xfail" is passed, then known bugs on ATI and nVidia will be ignored, and all tests will then succeed. The driver bugs don't seem due (solely) to hardware limitations, but may be due to software fallbacks being improperly implemented. There are two areas where the specification seems unclear, as far as I understand it. I'm not sure what the process to ask for clarification is, and suggestions would be welcome here. This first issue is whether, when fragment clamping is set to FIXED_ONLY and the FBO has some fixed-point and some floating-point buffers attached, gl_FragData[n] is never clamped, or is clamped only for the fixed point buffers. Note that while blending on fixed-point clamps the color anyway, alpha test and polygon smoothing happen before blending, and should be affected by whether gl_FragData[n] is clamped or not. From the OpenGL 4.1 spec, it seems that the intent is that fragment clamping does not depend on the target, especially because it can be bound dynamically due to user-defined varyings. None of the hardware I have access to supports such dishomogeneous FBOs, so I have no idea what the proprietary drivers do. Current nVidia cards might shed light on this. The second issue is whether disabling fragment clamping disables the clamping done before fog application in fragment shaders with ARB_fog_* options (or whether this is undefined) This happens in the fixed pipeline, but making it happen for shaders too would contradict the rationale of adding ARB_fog_* to shaders, which is to avoid recompilation. All the hardware I have access to has fixed function fog (all existing Radeons seem to have it), and here the disabling applies to fragment programs too, as a "naive" implementation would result in. Again, current nVidia cards might shed light on this.
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/spec/CMakeLists.txt1
-rw-r--r--tests/spec/arb_color_buffer_float/CMakeLists.txt30
-rw-r--r--tests/spec/arb_color_buffer_float/clear.c78
-rw-r--r--tests/spec/arb_color_buffer_float/common.h354
-rw-r--r--tests/spec/arb_color_buffer_float/drawpixels.c75
-rw-r--r--tests/spec/arb_color_buffer_float/getteximage.c54
-rw-r--r--tests/spec/arb_color_buffer_float/mrt.c135
-rw-r--r--tests/spec/arb_color_buffer_float/probepixel.c77
-rw-r--r--tests/spec/arb_color_buffer_float/queries.c141
-rw-r--r--tests/spec/arb_color_buffer_float/readpixels.c77
-rw-r--r--tests/spec/arb_color_buffer_float/render.c221
12 files changed, 1244 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 00e5e05e..3d3a892d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -9,6 +9,7 @@ add_subdirectory (glslparsertest)
add_subdirectory (asmparsertest)
add_subdirectory (shaders)
add_subdirectory (texturing)
+add_subdirectory (spec)
IF(OPENGL_egl_LIBRARY)
add_subdirectory (egl)
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
new file mode 100644
index 00000000..f7598481
--- /dev/null
+++ b/tests/spec/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory (arb_color_buffer_float)
diff --git a/tests/spec/arb_color_buffer_float/CMakeLists.txt b/tests/spec/arb_color_buffer_float/CMakeLists.txt
new file mode 100644
index 00000000..5e10dd86
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/CMakeLists.txt
@@ -0,0 +1,30 @@
+include_directories(
+ ${OPENGL_INCLUDE_PATH}
+ ${GLUT_INCLUDE_DIR}
+ ${piglit_SOURCE_DIR}/tests/spec/arb_color_buffer_float
+ ${piglit_SOURCE_DIR}/tests/util
+ ${GLEW_INCLUDE_DIR}
+)
+
+link_directories (
+ ${piglit_SOURCE_DIR}/tests/spec/arb_color_buffer_float
+ ${piglit_SOURCE_DIR}/tests/util
+)
+
+link_libraries (
+ piglitutil
+ ${OPENGL_gl_LIBRARY}
+ ${OPENGL_glu_LIBRARY}
+ ${GLUT_glut_LIBRARY}
+ ${TIFF_LIBRARY}
+ ${GLEW_glew_LIBRARY}
+)
+
+add_executable (arb_color_buffer_float-getteximage getteximage.c)
+add_executable (arb_color_buffer_float-queries queries.c)
+add_executable (arb_color_buffer_float-readpixels readpixels.c)
+add_executable (arb_color_buffer_float-probepixel probepixel.c)
+add_executable (arb_color_buffer_float-drawpixels drawpixels.c)
+add_executable (arb_color_buffer_float-clear clear.c)
+add_executable (arb_color_buffer_float-render render.c)
+add_executable (arb_color_buffer_float-mrt mrt.c)
diff --git a/tests/spec/arb_color_buffer_float/clear.c b/tests/spec/arb_color_buffer_float/clear.c
new file mode 100644
index 00000000..f8e58f50
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/clear.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/clear.c
+ *
+ * Tests that vertex and fragment color clamping do not affect glClear as
+ * specified by ARB_color_buffer_float
+ */
+
+/*
+ * (modify second paragraph, p. 216, removing clamp of clear color)
+ * void ClearColor(float r, float g, float b, float a);
+ * sets the clear value for the color buffers in RGBA mode.
+ *
+ * Fixed-point RGBA
+ * color buffers are cleared to a color values derived by taking the
+ * clear color, clamping to [0,1], and converting to fixed-point
+ * according to the rules of section 2.14.9.
+ */
+
+#include "common.h"
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+
+ for(vert_clamp = 0; vert_clamp < 3; ++vert_clamp)
+ {
+ for(frag_clamp = 0; frag_clamp < 3; ++frag_clamp)
+ {
+ GLboolean cpass;
+ printf("glClear of fbo for float texture with vertex clamp %s and fragment clamp %s (expecting no clamping)\n", clamp_strings[vert_clamp], clamp_strings[frag_clamp]);
+ glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, clamp_enums[vert_clamp]);
+ glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, clamp_enums[frag_clamp]);
+
+ glClearColor(pixels[0], pixels[1], pixels[2], pixels[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ expected = fixed ? clamped_pixels : pixels;
+
+ cpass = piglit_probe_pixel_rgba(0, 0, expected);
+ GLboolean opass = cpass;
+ if(!cpass && ati_driver && format == GL_RGBA16F_ARB)
+ {
+ printf("ATI driver known *** MAJOR BUG ***: they always clamp clears for fp16 targets!\n");
+ opass = GL_TRUE;
+ }
+ pass = opass && pass;
+ }
+ }
+ return pass;
+}
+
+unsigned init()
+{
+ return TEST_SRT;
+}
diff --git a/tests/spec/arb_color_buffer_float/common.h b/tests/spec/arb_color_buffer_float/common.h
new file mode 100644
index 00000000..a8e3bd64
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/common.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/common.h
+ *
+ * Common test framework for GL_ARB_color_buffer_float
+ *
+ * NOTE: both ATI and nVidia proprietary drivers are seriously broken, in
+ * different ways!
+ */
+
+#include "piglit-util.h"
+
+int piglit_width = 128;
+int piglit_height = 128;
+int piglit_window_mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE;
+
+/* use small values for pixels[0..3], so that the 0.01 tolerance is met for fp16 */
+float pixels[] = {
+ 7, -2.75, -0.25, 0.75,
+ 0.0, 1.0, 2.0, -1.0,
+ 0.5, 9.0 / 8.0, -156, 390,
+ 234, -86, -21.5, 46.5,
+};
+
+float clamped_pixels[16];
+float pixels_mul_2[16];
+float clamped_pixels_mul_2[16];
+float pixels_plus_half[16];
+float clamped_pixels_plus_half[16];
+float clamped_pixels_plus_half_clamped[16];
+
+const char* clamp_strings[] = {"TRUE", "FIXED_ONLY", "FALSE"};
+GLenum clamp_enums[] = {GL_TRUE, GL_FIXED_ONLY_ARB, GL_FALSE};
+
+const char* mrt_mode_strings[] = {"single target", "homogeneous framebuffer", "dishomogeneous framebuffer"};
+
+static inline float clamp(float f)
+{
+ if(f >= 0.0f && f <= 1.0f)
+ return f;
+ else if(f > 0.0f)
+ return 1.0f;
+ else
+ return 0.0f;
+}
+
+unsigned ati_driver;
+unsigned nvidia_driver;
+
+char test_name[4096];
+float observed[16];
+unsigned vert_clamp, frag_clamp, read_clamp;
+float* expected;
+float* expected1;
+GLuint tex, tex1, fb;
+GLenum status;
+unsigned error;
+
+int fbo_width = 2;
+int fbo_height = 2;
+
+#define TEST_NO_RT 0
+#define TEST_SRT 1
+#define TEST_MRT 2
+#define TEST_SRT_MRT 3
+
+int test_mode = TEST_SRT;
+
+GLenum format;
+const char* format_name;
+GLboolean fixed;
+GLboolean fixed0, fixed1;
+unsigned mrt_mode;
+
+GLboolean test();
+
+GLboolean run_test()
+{
+ GLboolean pass = GL_TRUE;
+ fixed = fixed0 = format == GL_RGBA8;
+ fixed1 = -1;
+
+ 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, format,
+ 2, 2, 0,
+ GL_RGBA, GL_FLOAT, pixels);
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after glTexImage2D 0x%04X\n", error);
+ return GL_FALSE;
+ }
+
+ if(test_mode)
+ {
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffersEXT(1, &fb);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
+ glViewport(0, 0, fbo_width, fbo_height);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D,
+ tex,
+ 0);
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after FBO 0x%04X\n", error);
+ return GL_FALSE;
+ }
+
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ fprintf(stderr, "fbo incomplete (status = 0x%04x)\n", status);
+ piglit_report_result(PIGLIT_SKIP);
+ }
+ }
+
+ if(test_mode <= TEST_SRT)
+ {
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
+ pass = test();
+ }
+ else
+ {
+ unsigned mrt_modes = GLEW_ARB_draw_buffers ? (GLEW_ARB_texture_float ? 3 : 2) : 1;
+ unsigned first_mrt_mode = (test_mode == TEST_MRT) ? 1 : 0;
+
+ for(mrt_mode = first_mrt_mode; mrt_mode < mrt_modes; ++mrt_mode)
+ {
+ fixed1 = fixed;
+ if(mrt_mode)
+ {
+ GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
+ unsigned format1;
+ if(mrt_mode == 1)
+ format1 = format;
+ else
+ {
+ format1 = fixed0 ? GL_RGBA32F_ARB : GL_RGBA8;
+ fixed1 = !fixed0;
+ fixed = GL_FALSE;
+ }
+
+ glGenTextures(1, &tex1);
+ glBindTexture(GL_TEXTURE_2D, tex1);
+ 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, format1,
+ 2, 2, 0,
+ GL_RGBA, GL_FLOAT, pixels);
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after second glTexImage2D 0x%04X\n", error);
+ return GL_FALSE;
+ }
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT1_EXT,
+ GL_TEXTURE_2D,
+ tex1,
+ 0);
+
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ if(mrt_mode == 2)
+ printf("Dishomogeneous framebuffer is incomplete, skipping dishomogeneous tests (status = 0x%04x)\n", status);
+ else
+ {
+ printf("Framebuffer is incomplete (status = 0x%04x)\n", status);
+ pass = GL_FALSE;
+ }
+ goto skip_mrt;
+ }
+
+ glDrawBuffers(2, bufs);
+
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after second glDrawBuffers 0x%04X\n", error);
+ return GL_FALSE;
+ }
+ }
+
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
+ pass = test() && pass;
+
+ skip_mrt:
+ if(mrt_mode)
+ {
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT1_EXT,
+ GL_TEXTURE_2D,
+ 0,
+ 0);
+ glDeleteTextures(1, &tex1);
+ }
+ }
+ }
+
+ glDeleteTextures(1, &tex);
+ tex = 0;
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ if(fb)
+ {
+ glDeleteFramebuffersEXT(1, &fb);
+ fb = 0;
+ }
+
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after test 0x%04X\n", error);
+ return GL_FALSE;
+ }
+
+ return pass;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+ GLboolean pass = GL_TRUE;
+ unsigned error;
+ printf("Testing 8-bit fixed-point FBO\n");
+ format = GL_RGBA8;
+ format_name = "un8";
+ pass = run_test() && pass;
+
+ if(GLEW_ARB_texture_float)
+ {
+ printf("\n\n\nTesting 32-bit floating point FBO\n");
+ format = GL_RGBA32F_ARB;
+ format_name = "f32";
+ pass = run_test() && pass;
+ printf("\n\n\nTesting 16-bit floating point FBO\n");
+ format = GL_RGBA16F_ARB;
+ format_name = "f16";
+ pass = run_test() && pass;
+ }
+ else
+ printf("\n\n\nSkipping floating point FBO tests because of no ARB_texture_float.\n");
+
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error at end 0x%04X\n", error);
+ return GL_FALSE;
+ }
+
+ return pass ? PIGLIT_SUCCESS : PIGLIT_FAILURE;
+}
+
+unsigned init();
+
+void
+piglit_init(int argc, char **argv)
+{
+ int i;
+ GLboolean distinguish_xfails = GL_FALSE;
+
+ (void)i;
+ /* displaying thousands of single-pixel floating point results isn't really useful, or even doable */
+ piglit_automatic = GL_TRUE;
+
+ piglit_require_extension("GL_ARB_color_buffer_float");
+
+ test_mode = init();
+
+ if(test_mode != TEST_NO_RT)
+ piglit_require_extension("GL_EXT_framebuffer_object");
+
+ for(i = 1; i < argc; ++i)
+ {
+ if(!strcmp(argv[i], "-xfail"))
+ distinguish_xfails = GL_TRUE;
+ }
+
+ /* current ATI drivers are broken */
+ if(!strcmp((char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
+ ati_driver = 1;
+
+ /* current nVidia drivers are broken at least on GeForce 7xxx */
+ if(!strcmp((char*)glGetString(GL_VENDOR), "NVIDIA Corporation"))
+ nvidia_driver = 1;
+
+ if(ati_driver || nvidia_driver)
+ {
+ /* print both so users don't think either driver is better */
+ printf("Notice: the ATI proprietary driver does NOT conform to the GL_ARB_color_buffer_float specification! (tested version was 10.6 on cypress, on Linux x86)\n");
+ printf("Notice: the nVidia proprietary driver does NOT conform to the GL_ARB_color_buffer_float specification! (tested version was 256.44 on nv49, on Linux x86)\n");
+ printf("Notice: the nVidia and ATI proprietary drivers are both nonconformant, in different ways!\n\n\n");
+ }
+
+ if(!distinguish_xfails)
+ ati_driver = nvidia_driver = 0;
+
+ for(i = 0; i < sizeof(pixels) / sizeof(pixels[0]); ++i)
+ {
+ clamped_pixels[i] = clamp(pixels[i]);
+ pixels_mul_2[i] = pixels[i] * 2.0f;
+ clamped_pixels_mul_2[i] = clamped_pixels[i] * 2.0f;
+ pixels_plus_half[i] = pixels[i] + 0.5f;
+ clamped_pixels_plus_half[i] = clamped_pixels[i] + 0.5f;
+ clamped_pixels_plus_half_clamped[i] = clamp(clamped_pixels_plus_half[i]);
+ }
+}
+
+GLboolean compare_arrays(float* expected, float* observed, int length)
+{
+ GLboolean pass = GL_TRUE;
+ unsigned i;
+ for(i = 0; i < length; ++i)
+ {
+ if(fabs(expected[i] - observed[i]) > 0.01)
+ {
+ printf("At %i Expected: %f Observed: %f\n", i, expected[i], observed[i]);
+ pass = GL_FALSE;
+ }
+ }
+
+ return pass;
+}
diff --git a/tests/spec/arb_color_buffer_float/drawpixels.c b/tests/spec/arb_color_buffer_float/drawpixels.c
new file mode 100644
index 00000000..2ac67fb1
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/drawpixels.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/drawpixels.c
+ *
+ * Tests that fragment color clamping affects glDrawPixels as specified by
+ * ARB_color_buffer_float
+ */
+
+/* 6. What control should apply to DrawPixels RGBA components?
+ * RESOLVED: The fragment color clamp control.
+ */
+
+#include "common.h"
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+
+ for(frag_clamp = 0; frag_clamp < 3; ++frag_clamp)
+ {
+ GLboolean cpass = GL_TRUE;
+ unsigned clamped = clamp_enums[frag_clamp] == GL_TRUE || (clamp_enums[frag_clamp] == GL_FIXED_ONLY_ARB && fixed);
+ printf("glDrawPixels of fbo for float texture with fragment clamp %s (expecting %sclamping)\n", clamp_strings[frag_clamp], clamped ? "" : "no ");
+ glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, clamp_enums[frag_clamp]);
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glWindowPos2fARB(0, 0);
+ glDrawPixels(2, 2, GL_RGBA, GL_FLOAT, pixels);
+
+ expected = ((clamped || fixed) ? clamped_pixels : pixels);
+ unsigned x, y;
+ for(y = 0; y < 2; ++y)
+ for(x = 0; x < 2; ++x)
+ cpass = piglit_probe_pixel_rgba(x, y, expected + 8 * y + 4 * x) && cpass;
+
+ GLboolean opass = cpass;
+ if(!cpass && nvidia_driver && clamped)
+ {
+ printf("nVidia driver known *** MAJOR BUG ***: they don't clamp glDrawPixels!\n");
+ opass = GL_TRUE;
+ }
+ pass = opass && pass;
+ }
+ return pass;
+}
+
+unsigned init()
+{
+ piglit_require_extension("GL_ARB_window_pos");
+ return TEST_SRT;
+}
diff --git a/tests/spec/arb_color_buffer_float/getteximage.c b/tests/spec/arb_color_buffer_float/getteximage.c
new file mode 100644
index 00000000..4d9dd9d1
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/getteximage.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/getteximage.c
+ *
+ * Tests that read color clamping doesn't affect glGetTexImage as
+ * specified by ARB_color_buffer_float
+ */
+
+#include "common.h"
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+
+ for(read_clamp = 0; read_clamp < 3; ++read_clamp)
+ {
+ printf("glGetTexImage of %s texture with read clamp %s (expecting %sclamping)\n", format_name, clamp_strings[read_clamp], fixed ? "" : "no ");
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, clamp_enums[read_clamp]);
+
+ memset(observed, 0, sizeof(observed));
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, observed);
+
+ expected = fixed ? clamped_pixels : pixels;
+ pass = compare_arrays(expected, observed, 16);
+ }
+ return pass;
+}
+
+unsigned init()
+{
+ return TEST_NO_RT;
+}
diff --git a/tests/spec/arb_color_buffer_float/mrt.c b/tests/spec/arb_color_buffer_float/mrt.c
new file mode 100644
index 00000000..52429b94
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/mrt.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/mrt.c
+ *
+ * Tests that fragment color clamping affects MRT rendering as
+ * specified by ARB_color_buffer_float and OpenGL 4.1
+ *
+ * Note that the specification is not fully clear here.
+* It *seems* to mean that clamping does *not* depend on the target framebuffer type,
+ * but rather the data type of the shader variable and whether there is *any* floating-point
+ * buffer in case of GL_FIXED_ONLY clamping.
+ *
+ * On ATI Radeon HD 58xx, dishomogeneous framebuffers are incomplete.
+ * TODO: what happens on GeForce 8xxx, GTX 2xx and GTX 4xx?
+ */
+
+/* If clamp is TRUE, fragment color
+ * clamping is enabled; if clamp is FALSE, fragment color clamping is disabled. If
+ * clamp is FIXED_ONLY, fragment color clamping is enabled if all enabled color
+ * buffers have fixed-point components.
+ *
+ * If fragment color clamping is enabled
+ * and the color buffer has an unsigned normalized fixed-point, signed normalized
+ * fixed-point, or floating-point format, the final fragment color, fragment data, or
+ * varying out variable values written by a fragment shader are clamped to the range
+ * [0, 1]. Only user-defined varying out variables declared as a floating-point type are
+ * clamped and may be converted. If fragment color clamping is disabled, or the color
+ * buffer has an integer format, the final fragment color, fragment data, or varying out
+ * variable values are not modified.
+ */
+
+#include "common.h"
+
+const char *mrt_vp_string =
+ "!!ARBvp1.0\n" "MOV result.position, vertex.position;\n"
+ "MOV result.texcoord[0], {7, -2.75, -0.25, 0.75};\n"
+ "MOV result.texcoord[1], {7, -2.75, -0.25, 0.75};\n" "END\n";
+
+const char *mrt_fp_string =
+ "!!ARBfp1.0\n" "OPTION ARB_draw_buffers;\n"
+ "MOV result.color[0], fragment.texcoord[0];\n"
+ "MOV result.color[1], fragment.texcoord[1];\n" "END\n";
+
+unsigned mrt_vp;
+unsigned mrt_fp;
+
+GLboolean
+test()
+{
+ GLboolean pass = GL_TRUE;
+
+ for(frag_clamp = 0; frag_clamp < 3; ++frag_clamp)
+ {
+ GLboolean cpass = GL_TRUE;
+ GLboolean clamped = clamp_enums[frag_clamp] == GL_TRUE || (clamp_enums[frag_clamp] == GL_FIXED_ONLY_ARB && fixed);
+
+ printf("MRT rendering in %s mode with fragment clamp %s (expecting %sclamping)\n", mrt_mode_strings[mrt_mode], clamp_strings[frag_clamp], clamped ? "" : "no ");
+ glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, clamp_enums[frag_clamp]);
+
+ glBindProgramARB(GL_VERTEX_PROGRAM_ARB, mrt_vp);
+ glEnable(GL_VERTEX_PROGRAM_ARB);
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, mrt_fp);
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+
+ glClearColor(0.5, 0.5, 0.5, 0.5);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ piglit_draw_rect(-1, -1, 1, 1);
+
+ glDisable(GL_VERTEX_PROGRAM_ARB);
+ glDisable(GL_FRAGMENT_PROGRAM_ARB);
+
+ expected = (clamped || fixed0) ? clamped_pixels : pixels;
+ expected1 = (clamped || fixed1) ? clamped_pixels : pixels;
+
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ printf("Probing buffer 0 (%s)\n", fixed ? "fixed point" : "floating point");
+ cpass = piglit_probe_pixel_rgba(0, 0, expected) && cpass;
+ glReadBuffer(GL_COLOR_ATTACHMENT1);
+ printf("Probing buffer 1 (%s)\n", fixed1 ? "fixed point" : "floating point");
+ cpass = piglit_probe_pixel_rgba(0, 0, expected1) && cpass;
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after MRT 0x%04X\n", error);
+ return GL_FALSE;
+ }
+
+ GLboolean opass = cpass;
+ if(!cpass && nvidia_driver && !fixed && clamped)
+ {
+ printf("nVidia driver ***MAJOR BUG***: they never clamp when using MRT on floating point targets!\n");
+ opass = GL_TRUE;
+ }
+ pass = opass && pass;
+ }
+ return pass;
+}
+
+unsigned
+init()
+{
+ piglit_require_extension("GL_ARB_vertex_program");
+ piglit_require_extension("GL_ARB_fragment_program");
+ piglit_require_extension("GL_ARB_draw_buffers");
+
+ mrt_vp = piglit_compile_program(GL_VERTEX_PROGRAM_ARB, mrt_vp_string);
+ mrt_fp = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, mrt_fp_string);
+
+ return TEST_MRT;
+}
diff --git a/tests/spec/arb_color_buffer_float/probepixel.c b/tests/spec/arb_color_buffer_float/probepixel.c
new file mode 100644
index 00000000..9ca65a6c
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/probepixel.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/probepixel.c
+ *
+ * Tests that read color clamping affects 1x1 glReadPixels as specified by
+ * ARB_color_buffer_float
+ *
+ * This is a separate test from the 2x2 glReadPixels because some
+ * implementations (e.g. ATI's) are broken, since they presumably
+ * special-case it incorrectly.
+ */
+
+#include "common.h"
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+
+ for(read_clamp = 0; read_clamp < 3; ++read_clamp)
+ {
+ unsigned clamped = clamp_enums[read_clamp] == GL_TRUE || (clamp_enums[read_clamp] == GL_FIXED_ONLY_ARB && fixed);
+ printf("probe_pixel of fbo for float texture with read clamp %s (expecting %sclamping)\n", clamp_strings[read_clamp], clamped ? "" : "no ");
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, clamp_enums[read_clamp]);
+
+ expected = (fixed || clamped) ? clamped_pixels : pixels;
+
+ unsigned x, y;
+ for(y = 0; y < 2; ++y)
+ for(x = 0; x < 2; ++x)
+ {
+ GLboolean cpass = piglit_probe_pixel_rgba(x, y, expected + 8 * y + 4 * x);
+ GLboolean opass = cpass;
+ if(!cpass && clamped && ati_driver)
+ {
+ printf("ATI driver known bug: 1x1 glReadPixels ignores the read clamp!\n");
+ opass = GL_TRUE;
+ }
+ if(!cpass && nvidia_driver && clamped)
+ {
+ printf("nVidia driver known *** MAJOR BUG ***: they ignore the read clamp!\n");
+ opass = GL_TRUE;
+ }
+ pass = opass && pass;
+ }
+ }
+
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
+ return pass;
+}
+
+unsigned
+init()
+{
+ return TEST_SRT;
+}
diff --git a/tests/spec/arb_color_buffer_float/queries.c b/tests/spec/arb_color_buffer_float/queries.c
new file mode 100644
index 00000000..0946ca7c
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/queries.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/queries.c
+ *
+ * Tests that fragment color clamping affects queries as specified by
+ * ARB_color_buffer_float
+ */
+
+/* Modify Section 6.1.2, Data Conversions, p. 245
+ * (add new paragraph at the end of the section, p. 245) If fragment
+ * color clamping is enabled, querying of the texture border color,
+ * texture environment color, fog color, alpha test reference value,
+ * blend color, and RGBA clear color will clamp the corresponding
+ * state values to [0,1] before returning them. This behavior
+ * provides compatibility with previous versions of the GL that
+ * clamped these values when specified.
+ */
+
+#include "common.h"
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+ glBindTexture(GL_TEXTURE_2D, tex); /* for border color */
+
+ for(frag_clamp = 0; frag_clamp < 3; ++frag_clamp)
+ {
+ const char *value_names[] = { "texture border color", "texenv color", "fog color", "alpha test reference", "blend color", "clear color" };
+ unsigned value;
+ for(value = 0; value < 6; ++value)
+ {
+ GLboolean cpass = GL_TRUE;
+ unsigned clamped = clamp_enums[frag_clamp] == GL_TRUE || (clamp_enums[frag_clamp] == GL_FIXED_ONLY_ARB && fixed);
+ unsigned comps = 4;
+
+ sprintf(test_name, "glGet of %s in %s mode with fragment clamp %s (expecting %sclamping)", value_names[value], mrt_mode_strings[mrt_mode], clamp_strings[frag_clamp], clamped ? "" : "no ");
+ printf("%s\n", test_name);
+
+ glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, clamp_enums[frag_clamp]);
+
+ memset(observed, 0, sizeof(observed));
+ switch (value)
+ {
+ case 0:
+ /* ARB_color_buffer_float adds a potential clamp on queries, but only ARB_texture_float removes
+ * the clamp on setting the texture border color */
+ if(!GLEW_ARB_texture_float)
+ clamped = 1;
+ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, pixels);
+ glGetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, observed);
+ break;
+ case 1:
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, pixels);
+ glGetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, observed);
+ break;
+ case 2:
+ glFogfv(GL_FOG_COLOR, pixels);
+ glGetFloatv(GL_FOG_COLOR, observed);
+ break;
+ case 3:
+ glAlphaFunc(GL_ALWAYS, pixels[0]);
+ glGetFloatv(GL_ALPHA_TEST_REF, observed);
+ comps = 1;
+ break;
+ case 4:
+ glBlendColor(pixels[0], pixels[1], pixels[2], pixels[3]);
+ glGetFloatv(GL_BLEND_COLOR, observed);
+ break;
+ case 5:
+ glClearColor(pixels[0], pixels[1], pixels[2], pixels[3]);
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, observed);
+ break;
+ }
+
+ error = glGetError();
+ if(error)
+ {
+ printf("GL error after query 0x%04X\n", error);
+ cpass = GL_FALSE;
+ }
+
+ expected = clamped ? clamped_pixels : pixels;
+ cpass = compare_arrays(expected, observed, comps) && cpass;
+
+ GLboolean opass = cpass;
+ if(!cpass && !clamped && ati_driver && value == 0)
+ {
+ printf("ATI driver known bug: they always clamp queries for the texture border color!\n");
+ opass = GL_TRUE;
+ }
+ if(!cpass && clamped && ati_driver && value == 5)
+ {
+ printf("ATI driver known bug: they don't clamp queries for the clear color!\n");
+ opass = GL_TRUE;
+ }
+ if(!cpass && !clamped && ati_driver && clamp_enums[frag_clamp] == GL_FIXED_ONLY_ARB && !fixed)
+ {
+ printf("ATI driver known bug: they clamp queries when FIXED_ONLY is set and the FBO is floating point!\n");
+ opass = GL_TRUE;
+ }
+ if(!cpass && clamped && nvidia_driver && value == 0)
+ {
+ printf("nVidia driver known bug: they don't clamp queries for the texture border color!\n");
+ opass = GL_TRUE;
+ }
+ printf("%s: %s\n", (cpass ? "PASS" : (opass ? "XFAIL" : "FAIL")), test_name);
+ pass = opass && pass;
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return pass;
+}
+
+unsigned
+init()
+{
+ return TEST_SRT_MRT;
+}
diff --git a/tests/spec/arb_color_buffer_float/readpixels.c b/tests/spec/arb_color_buffer_float/readpixels.c
new file mode 100644
index 00000000..de782102
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/readpixels.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/readpixels.c
+ *
+ * Tests that read color clamping affects 2x2 glReadPixels as specified by
+ * ARB_color_buffer_float
+ */
+
+/*
+ * Modify Section 4.3.2 (Reading Pixels), p. 219
+ * [...]
+ * (modify second paragraph of "Final Conversion", p. 222) For an
+ * RGBA color, if <type> is not FLOAT, or if the CLAMP_READ_COLOR_ARB
+ * is TRUE, or CLAMP_READ_COLOR_ARB is FIXED_ONLY_ARB and the selected
+ * color buffer is a fixed-point buffer, each component is first
+ * clamped to [0,1]. Then the appropriate conversion...
+ */
+
+#include "common.h"
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+
+ for(read_clamp = 0; read_clamp < 3; ++read_clamp)
+ {
+ GLboolean cpass = GL_TRUE;
+ unsigned clamped = clamp_enums[read_clamp] == GL_TRUE || (clamp_enums[read_clamp] == GL_FIXED_ONLY_ARB && fixed);
+
+ printf("glReadPixels of fbo for float texture with read clamp %s (expecting %sclamping)\n", clamp_strings[read_clamp], clamped ? "" : "no ");
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, clamp_enums[read_clamp]);
+
+ memset(observed, 0, sizeof(observed));
+ glReadPixels(0, 0, 2, 2, GL_RGBA, GL_FLOAT, observed);
+
+ expected = (fixed || clamped) ? clamped_pixels : pixels;
+ cpass = compare_arrays(expected, observed, 4);
+
+ GLboolean opass = cpass;
+ if(!cpass && nvidia_driver && clamped)
+ {
+ printf("nVidia driver known *** MAJOR BUG ***: they ignore the read clamp!\n");
+ opass = GL_TRUE;
+ }
+ pass = opass && pass;
+ }
+
+ glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
+ return pass;
+}
+
+unsigned init()
+{
+ return TEST_SRT;
+}
diff --git a/tests/spec/arb_color_buffer_float/render.c b/tests/spec/arb_color_buffer_float/render.c
new file mode 100644
index 00000000..4da6a62c
--- /dev/null
+++ b/tests/spec/arb_color_buffer_float/render.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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 spec/arb_color_buffer_float/render.c
+ *
+ * Tests that vertex and fragment color clamping affects rendering as
+ * specified by ARB_color_buffer_float.
+ *
+ * It also checks that fog, blending and logic op are done as specified by
+ * ARB_color_buffer_float.
+ *
+ * Note that it's unclear what should happen when ARB_fog is specified in
+ * the fragment program and fragment clamping is disabled: does the
+ * color still get clamped before applying fog?
+ *
+ * Both ATI and nVidia do that, but they have fixed function fog in the tested
+ * cards.
+ * TODO: what happens on GeForce 8xxx, GTX 2xx and GTX 4xx?
+ */
+
+#include "common.h"
+
+const char *blend_strings[] = { "disabled", "(ONE, ZERO)", "(CONSTANT_COLOR, ZERO)", "(ONE, ONE)" };
+GLenum blend_src[] = { 0, GL_ONE, GL_CONSTANT_COLOR, GL_ONE };
+GLenum blend_dst[] = { 0, GL_ZERO, GL_ZERO, GL_ONE };
+
+const char *vp_strings[] = {
+ "!!ARBvp1.0\n"
+ "MOV result.position, vertex.position;\n"
+ "MOV result.color, {7, -2.75, -0.25, 0.75};\n" "END\n",
+
+ "!!ARBvp1.0\n"
+ "MOV result.position, vertex.position;\n"
+ "MOV result.texcoord[0], {7, -2.75, -0.25, 0.75};\n" "END\n"
+};
+
+const char *fp_strings[] = {
+ "!!ARBfp1.0\n"
+ "MOV result.color, fragment.color;\n"
+ "END\n",
+
+ "!!ARBfp1.0\n"
+ "MOV result.color, fragment.texcoord[0];\n"
+ "END\n",
+
+ "!!ARBfp1.0\n"
+ "OPTION ARB_fog_linear;\n"
+ "MOV result.color, fragment.color;\n"
+ "END\n",
+
+ "!!ARBfp1.0\n"
+ "OPTION ARB_fog_linear;\n"
+ "MOV result.color, fragment.texcoord[0];\n"
+ "END\n",
+};
+
+unsigned vps[2];
+unsigned fps[4];
+
+GLboolean test()
+{
+ GLboolean pass = GL_TRUE;
+ unsigned semantic, blend, logicop, vpmode, fpmode, fog;
+ unsigned vpmodes = 1 + !!GLEW_ARB_vertex_program;
+ unsigned fpmodes = 1 + !!GLEW_ARB_fragment_program;
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+
+ for(vert_clamp = 0; vert_clamp < 3; ++vert_clamp)
+ for(frag_clamp = 0; frag_clamp < 3; ++frag_clamp)
+ for(semantic = 0; semantic < 2; ++semantic)
+ for(blend = 0; blend < 4; ++blend)
+ for(logicop = 0; logicop < 2; ++logicop)
+ for(vpmode = 0; vpmode < vpmodes; ++vpmode)
+ for(fpmode = 0; fpmode < fpmodes; ++fpmode)
+ for(fog = 0; fog < 2; ++fog)
+ {
+ unsigned clamped = (semantic == 0 && (clamp_enums[vert_clamp] == GL_TRUE || (clamp_enums[vert_clamp] == GL_FIXED_ONLY_ARB && fixed))) || clamp_enums[frag_clamp] == GL_TRUE || (clamp_enums[frag_clamp] == GL_FIXED_ONLY_ARB && fixed);
+ float *expected;
+ GLboolean cpass;
+
+ if(!fpmode && semantic)
+ continue;
+
+ sprintf(test_name, "%s: render constant through %s with vertex clamp %s and fragment clamp %s and blending %s and logicop %s using %s and %s%s (expecting %sclamping)", format_name, semantic ? "TEXCOORD0" : "COLOR", clamp_strings[vert_clamp], clamp_strings[frag_clamp], blend_strings[blend], logicop ? "enabled" : "disabled", vpmode ? "ARB_vp" : "ffvp", fpmode ? "ARB_fp" : "fffp", fog ? " with fog" : "", clamped ? "" : "no ");
+ printf("%s\n", test_name);
+ glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, clamp_enums[vert_clamp]);
+ glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, clamp_enums[frag_clamp]);
+
+ glColor4f(0.1f, 0.2f, 0.3f, 0.4f);
+ glTexCoord4f(0.5f, 0.6f, 0.7f, 0.8f);
+
+ if(vpmode)
+ {
+ glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vps[semantic]);
+ glEnable(GL_VERTEX_PROGRAM_ARB);
+ }
+ else
+ {
+ if(semantic == 0)
+ glColor4f(pixels[0], pixels[1], pixels[2], pixels[3]);
+ else
+ glTexCoord4f(pixels[0], pixels[1], pixels[2], pixels[3]);
+ }
+
+ if(fpmode)
+ {
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fps[semantic + (fog ? 2 : 0)]);
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+ }
+ else
+ {
+ if(fog)
+ glEnable(GL_FOG);
+ }
+
+ glClearColor(0.5, 0.5, 0.5, 0.5);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if(blend)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(blend_src[blend], blend_dst[blend]);
+ glBlendColor(2.0f, 2.0f, 2.0f, 2.0f);
+ }
+ if(logicop)
+ glEnable(GL_COLOR_LOGIC_OP);
+
+ piglit_draw_rect(-1, -1, 1, 1);
+
+ if(logicop)
+ glDisable(GL_COLOR_LOGIC_OP);
+ if(blend)
+ glDisable(GL_BLEND);
+ if(vpmode)
+ glDisable(GL_VERTEX_PROGRAM_ARB);
+ if(fpmode)
+ glDisable(GL_FRAGMENT_PROGRAM_ARB);
+ else if(fog)
+ glDisable(GL_FOG);
+
+ if(blend == 2 && !logicop)
+ {
+ if(fixed)
+ expected = clamped_pixels;
+ else
+ expected = clamped ? clamped_pixels_mul_2 : pixels_mul_2;
+ }
+ else if(blend == 3 && !logicop)
+ {
+ if(fixed)
+ expected = clamped_pixels_plus_half_clamped;
+ else
+ expected = clamped ? clamped_pixels_plus_half : pixels_plus_half;
+ }
+ else
+ expected = (clamped || fixed) ? clamped_pixels : pixels;
+
+ GLboolean opass = cpass = piglit_probe_pixel_rgba(0, 0, expected);
+
+ if(!cpass && nvidia_driver && clamped && !(semantic == 0 && clamp_enums[vert_clamp] == GL_TRUE) && clamp_enums[frag_clamp] == GL_TRUE && !fixed && fpmode && (!blend || logicop || format == GL_RGBA16F_ARB))
+ {
+ printf("nVidia driver known *** MAJOR BUG ***: they don't clamp fragment program results with ARB_fp on either fp32 with no blending or fp16!\n");
+ opass = GL_TRUE;
+ }
+ if(!cpass && nvidia_driver && clamped && !fixed && !fpmode && semantic == 0 && clamp_enums[vert_clamp] != GL_TRUE && clamp_enums[frag_clamp] == GL_TRUE)
+ {
+ printf("nVidia driver known *** MAJOR BUG ***: they don't clamp fragment program results with fffp, vertex clamp off and fragment clamp on fp16/fp32!\n");
+ opass = GL_TRUE;
+ }
+ if(!cpass && fog && fpmode)
+ {
+ printf("Unclear specification on GL_ARB_fog_*\n");
+ opass = GL_TRUE;
+ }
+ printf("%s: %s\n", (cpass ? "PASS" : (opass ? "XFAIL" : "FAIL")), test_name);
+ pass = opass && pass;
+ }
+
+ return pass;
+}
+
+unsigned
+init()
+{
+ if(GLEW_ARB_vertex_program)
+ {
+ unsigned i;
+ for(i = 0; i < 2; ++i)
+ vps[i] = piglit_compile_program(GL_VERTEX_PROGRAM_ARB, vp_strings[i]);
+ }
+
+ if(GLEW_ARB_fragment_program)
+ {
+ unsigned i;
+ for(i = 0; i < 4; ++i)
+ fps[i] = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, fp_strings[i]);
+ }
+
+ return TEST_SRT;
+}