[Piglit] [PATCH 3/3] Test blending a fast clear color with GL_FRAMEBUFFER_SRGB enabled

Neil Roberts neil at linux.intel.com
Wed Nov 25 03:22:37 PST 2015


On SKL in the i965 driver there is some special handling of the fast
clear optimisation when GL_FRAMEBUFFER_SRGB is enabled because the
hardware can't cope with the fast clear buffer in that case and the
color buffer needs to be resolved. This test just tries varies
different clear colors and enabling at GL_FRAMEBUFFER_SRGB at
different points to make sure this resolving works correctly.
---
 tests/all.py                                       |   1 +
 tests/spec/arb_framebuffer_srgb/CMakeLists.gl.txt  |   1 +
 tests/spec/arb_framebuffer_srgb/fast-clear-blend.c | 238 +++++++++++++++++++++
 3 files changed, 240 insertions(+)
 create mode 100644 tests/spec/arb_framebuffer_srgb/fast-clear-blend.c

diff --git a/tests/all.py b/tests/all.py
index 1893ccc..a069c78 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -2047,6 +2047,7 @@ with profile.group_manager(
       'msaa-fast-clear')
     g(['fbo-fast-clear', 'GL_EXT_texture_sRGB', 'enable-fb-srgb'],
       'fbo-fast-clear')
+    g(['fast-clear-blend'])
 
 with profile.group_manager(
         PiglitGLTest,
diff --git a/tests/spec/arb_framebuffer_srgb/CMakeLists.gl.txt b/tests/spec/arb_framebuffer_srgb/CMakeLists.gl.txt
index 04609b8..fc1eb57 100644
--- a/tests/spec/arb_framebuffer_srgb/CMakeLists.gl.txt
+++ b/tests/spec/arb_framebuffer_srgb/CMakeLists.gl.txt
@@ -12,4 +12,5 @@ piglit_add_executable (arb_framebuffer_srgb-pushpop pushpop.c)
 piglit_add_executable (arb_framebuffer_srgb-blit blit.c)
 piglit_add_executable (arb_framebuffer_srgb-clear clear.c)
 piglit_add_executable (arb_framebuffer_srgb-srgb_conformance srgb_conformance.c)
+piglit_add_executable (arb_framebuffer_srgb-fast-clear-blend fast-clear-blend.c)
 
diff --git a/tests/spec/arb_framebuffer_srgb/fast-clear-blend.c b/tests/spec/arb_framebuffer_srgb/fast-clear-blend.c
new file mode 100644
index 0000000..c8fe723
--- /dev/null
+++ b/tests/spec/arb_framebuffer_srgb/fast-clear-blend.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2015 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 fast-clear-blend.c
+ *
+ * Enables GL_FRAMEBUFFER_SRGB, clears the buffer to a color and then
+ * blends it with a rectangle in another color before verifying the
+ * result. This is mainly to test fast clears on SKL in the i965
+ * driver because in that case fast clears can't be used with
+ * GL_FRAMEBUFFER_SRGB so it internally needs to resolve the color
+ * buffer.
+ */
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_compat_version = 21;
+	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char
+vertex_source[] =
+	"attribute vec4 piglit_vertex;\n"
+	"\n"
+	"void\n"
+	"main()\n"
+	"{\n"
+	"	 gl_Position = piglit_vertex;\n"
+	"}\n";
+
+static const char
+fragment_source[] =
+	"uniform vec4 color;\n"
+	"\n"
+	"void\n"
+	"main()\n"
+	"{\n"
+	"	 gl_FragColor = color;\n"
+	"}\n";
+
+static GLuint prog;
+static GLuint fbo;
+static GLint color_location;
+
+static const float
+clear_colors[][4] = {
+	{ 0.0f, 0.0f, 0.0f, 0.0f },
+	{ 1.0f, 1.0f, 1.0f, 1.0f },
+	{ 0.0f, 0.0f, 1.0f, 0.0f },
+	{ 1.0f, 0.0f, 0.0f, 1.0f },
+
+	{ 0.25f, 0.5f, 0.75f, 1.0f },
+	{ 0.75f, 0.5f, 0.25f, 0.0f },
+	{ 0.5f, 0.25f, 0.75f, 0.5f },
+};
+
+static bool
+probe_srgb_color(int x, int y, int w, int h,
+		 const GLfloat *color)
+{
+	GLfloat srgb_color[4];
+	int i;
+
+	/* The value in the framebuffer is stored in SRGB space so we
+	 * need to convert to that.
+	 */
+	for (i = 0; i < 3; i++)
+		srgb_color[i] = piglit_linear_to_srgb(color[i]);
+	srgb_color[3] = color[3];
+
+	return piglit_probe_rect_rgba(x, y, w, h, srgb_color);
+}
+
+static bool
+test_color(bool srgb_before_clear,
+	   const GLfloat *clear_color)
+{
+	static const GLfloat rect_color[] = {
+		0.0f, 0.75f, 1.0f, 0.5f
+	};
+	GLfloat expected_color[4];
+	GLfloat fb_color;
+	bool pass = true;
+	int i;
+
+	printf("Clear to %f,%f,%f,%f - SRGB enabled %s clear\n",
+	       clear_color[0],
+	       clear_color[1],
+	       clear_color[2],
+	       clear_color[3],
+	       srgb_before_clear ? "before" : "after");
+
+	if (srgb_before_clear)
+		glEnable(GL_FRAMEBUFFER_SRGB);
+
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+	glClearColor(clear_color[0],
+		     clear_color[1],
+		     clear_color[2],
+		     clear_color[3]);
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	if (!srgb_before_clear)
+		glEnable(GL_FRAMEBUFFER_SRGB);
+
+	glUseProgram(prog);
+	glUniform4fv(color_location, 1, rect_color);
+
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+	/* Blend a rectangle into the right-hand half of the framebuffer */
+	piglit_draw_rect(0.0f, -1.0f, 1.0f, 2.0f);
+
+	glDisable(GL_BLEND);
+	glDisable(GL_FRAMEBUFFER_SRGB);
+
+	if (srgb_before_clear) {
+		pass = probe_srgb_color(0, 0,
+					piglit_width / 2, piglit_height,
+					clear_color) && pass;
+	} else {
+		pass = piglit_probe_rect_rgba(0, 0,
+					      piglit_width / 2, piglit_height,
+					      clear_color) && pass;
+	}
+
+	/* Calculate the expected blended color. The blending will be
+	 * done in linear space so if GL_FRAMEBUFFER_SRGB was enabled
+	 * before the clear then the SRGB conversions cancel out and
+	 * don't affect the result. However if it wasn't enabled then
+	 * the clear color will go through an SRGB→linear conversion
+	 * before being used as one of the sources for the blend.
+	 */
+	for (i = 0; i < 4; i++) {
+		if (i >= 3 || srgb_before_clear)
+			fb_color = clear_color[i];
+		else
+			fb_color = piglit_srgb_to_linear(clear_color[i]);
+
+		expected_color[i] = (fb_color * (1.0f - rect_color[3]) +
+				     rect_color[i] * rect_color[3]);
+	}
+
+	pass = probe_srgb_color(piglit_width / 2, 0,
+				piglit_width / 2, piglit_height,
+				expected_color) && pass;
+
+	/* Copy the test framebuffer into the winsys framebuffer so
+	 * that something will be visible */
+	glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
+	glBlitFramebuffer(0, 0, piglit_width, piglit_height,
+			  0, 0, piglit_width, piglit_height,
+			  GL_COLOR_BUFFER_BIT,
+			  GL_NEAREST);
+
+	glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
+
+	piglit_present_results();
+
+	return pass;
+}
+
+enum piglit_result
+piglit_display()
+{
+	bool pass = true;
+	int srgb_before_clear;
+	int i;
+
+	for (srgb_before_clear = 0;
+	     srgb_before_clear < 2;
+	     srgb_before_clear++) {
+		for (i = 0; i < ARRAY_SIZE(clear_colors); i++) {
+			pass = test_color(srgb_before_clear,
+					  clear_colors[i]) && pass;
+		}
+	}
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLuint rb;
+
+	piglit_require_extension("GL_EXT_framebuffer_sRGB");
+	piglit_require_extension("GL_ARB_framebuffer_sRGB");
+
+	prog = piglit_build_simple_program(vertex_source, fragment_source);
+
+	color_location = glGetUniformLocation(prog, "color");
+
+	glGenFramebuffers(1, &fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+	glGenRenderbuffers(1, &rb);
+	glBindRenderbuffer(GL_RENDERBUFFER, rb);
+	glRenderbufferStorage(GL_RENDERBUFFER,
+			      GL_SRGB8_ALPHA8,
+			      piglit_width, piglit_height);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+				  GL_COLOR_ATTACHMENT0,
+				  GL_RENDERBUFFER,
+				  rb);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
+	    GL_FRAMEBUFFER_COMPLETE) {
+		fprintf(stderr, "FBO incomplete\n");
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
+}
-- 
1.9.3



More information about the Piglit mailing list