[Piglit] [PATCH 2/5] Test reading from a buffer after fast clearing it.

Paul Berry stereotype441 at gmail.com
Wed May 22 10:20:24 PDT 2013


---
 tests/CMakeLists.txt                      |   1 +
 tests/all.tests                           |   7 +
 tests/fast_color_clear/CMakeLists.gl.txt  |  15 ++
 tests/fast_color_clear/CMakeLists.txt     |   1 +
 tests/fast_color_clear/read-after-clear.c | 309 ++++++++++++++++++++++++++++++
 5 files changed, 333 insertions(+)
 create mode 100644 tests/fast_color_clear/CMakeLists.gl.txt
 create mode 100644 tests/fast_color_clear/CMakeLists.txt
 create mode 100644 tests/fast_color_clear/read-after-clear.c

diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a85af2a..f842458 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -15,6 +15,7 @@ add_subdirectory (security)
 add_subdirectory (shaders)
 add_subdirectory (texturing)
 add_subdirectory (spec)
+add_subdirectory (fast_color_clear)
 
 add_subdirectory (glean)
 
diff --git a/tests/all.tests b/tests/all.tests
index 267e769..fed16d7 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -2329,6 +2329,13 @@ add_plain_test(hiz, 'hiz-stencil-test-window-depth1')
 fast_color_clear = Group()
 add_shader_test_dir(fast_color_clear, testsDir + '/fast_color_clear',
                     recursive=True)
+for subtest in ('sample', 'read_pixels', 'blit', 'copy'):
+        for buffer_type in ('rb', 'tex'):
+                if subtest == 'sample' and buffer_type == 'rb':
+                        continue
+                test_name = ' '.join(
+                        ['fcc-read-after-clear', subtest, buffer_type])
+                add_concurrent_test(fast_color_clear, test_name)
 
 asmparsertest = Group()
 def add_asmparsertest(group, shader):
diff --git a/tests/fast_color_clear/CMakeLists.gl.txt b/tests/fast_color_clear/CMakeLists.gl.txt
new file mode 100644
index 0000000..087cefa
--- /dev/null
+++ b/tests/fast_color_clear/CMakeLists.gl.txt
@@ -0,0 +1,15 @@
+
+include_directories(
+	${GLEXT_INCLUDE_DIR}
+	${OPENGL_INCLUDE_PATH}
+)
+
+link_libraries (
+	piglitutil_${piglit_target_api}
+	${OPENGL_gl_LIBRARY}
+	${OPENGL_glu_LIBRARY}
+)
+
+piglit_add_executable (fcc-read-after-clear read-after-clear.c)
+
+# vim: ft=cmake:
diff --git a/tests/fast_color_clear/CMakeLists.txt b/tests/fast_color_clear/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/fast_color_clear/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/fast_color_clear/read-after-clear.c b/tests/fast_color_clear/read-after-clear.c
new file mode 100644
index 0000000..d635fd2
--- /dev/null
+++ b/tests/fast_color_clear/read-after-clear.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright © 2013 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 read-after-clear.c
+ *
+ * Test that fast color clears of an off-screen buffer work properly
+ * when they are followed by various ways of reading from the buffer.
+ *
+ * There are four sub-tests (selectable by a command line parameter)
+ * for each of the following ways of reading from the texture buffer:
+ *
+ * - sample: read by sampling via a GLSL shader.
+ * - read_pixels: read using the glReadPixels() function.
+ * - blit: read by blitting from the texture to the windowsystem framebuffer.
+ * - copy: read by copying to a second texture using glCopyTexImage2D.
+ *
+ * In addition, each test can be qualified with "rb" or "tex" to
+ * choose whether the off-screen buffer is a texture or a
+ * renderbuffer.  Note that the "rb" option is not allowed for the
+ * "sample" sub-test.
+ *
+ * The test operates by creating an off-screen buffer, painting it red
+ * using a non-fast-clear technique (rendering a quad using a shader),
+ * and then clearing it to green using a fast clear.  Then it reads
+ * from the buffer using the technique specified on the command line,
+ * to verify that the fast clear data got successfully written to the
+ * buffer.
+ */
+
+#include "piglit-util-gl-common.h"
+
+#define TEX_WIDTH 512
+#define TEX_HEIGHT 512
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+	config.supports_gl_compat_version = 11;
+	config.window_width = TEX_WIDTH;
+	config.window_height = TEX_HEIGHT;
+	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
+PIGLIT_GL_TEST_CONFIG_END
+
+
+static enum subtest_enum {
+	SUBTEST_SAMPLE,
+	SUBTEST_READ_PIXELS,
+	SUBTEST_BLIT,
+	SUBTEST_COPY,
+} subtest;
+
+static bool use_texture;
+
+
+static const char *vs_text =
+	"void main()\n"
+	"{\n"
+	"  gl_Position = gl_Vertex;\n"
+	"  gl_TexCoord[0] = gl_MultiTexCoord0;\n"
+	"}\n";
+
+static const char *fs_text_paint_red =
+	"void main()\n"
+	"{\n"
+	"  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
+	"}\n";
+
+static const char *fs_text_sample =
+	"uniform sampler2D samp;\n"
+	"void main()\n"
+	"{\n"
+	"  gl_FragColor = texture2D(samp, gl_TexCoord[0].xy);\n"
+	"}\n";
+
+static GLuint prog_paint_red, prog_sample, tex1, tex2, fb;
+
+
+static void
+print_usage_and_exit(const char *prog_name)
+{
+	printf("Usage: %s <subtest> <buffer_type>\n"
+	       "  where <subtest> is one of the following:\n"
+	       "    sample: read by sampling from the cleared buffer\n"
+	       "    read_pixels: read using glReadPixels()\n"
+	       "    blit: read by blitting from the cleared buffer\n"
+	       "    copy: read using glCopyTexImage2D()\n"
+	       "  and <buffer_type> is one of the following:\n"
+	       "    rb: off-screen buffer is a renderbuffer\n"
+	       "    tex: off-screen buffer is a texture\n", prog_name);
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+
+static GLuint allocate_texture()
+{
+	GLuint tex;
+	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 /* level */,
+		     GL_RGBA /* internal format */,
+		     TEX_WIDTH, TEX_HEIGHT,
+		     0 /* border */,
+		     GL_RGBA /* format */,
+		     GL_BYTE /* type */,
+		     NULL /* data */);
+	return tex;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLuint vs, fs_paint_red, fs_sample;
+	GLenum fb_status;
+
+	/* Parse params */
+	if (argc != 3)
+		print_usage_and_exit(argv[0]);
+	if (strcmp(argv[1], "sample") == 0)
+		subtest = SUBTEST_SAMPLE;
+	else if (strcmp(argv[1], "read_pixels") == 0)
+		subtest = SUBTEST_READ_PIXELS;
+	else if (strcmp(argv[1], "blit") == 0)
+		subtest = SUBTEST_BLIT;
+	else if (strcmp(argv[1], "copy") == 0)
+		subtest = SUBTEST_COPY;
+	else
+		print_usage_and_exit(argv[0]);
+	if (strcmp(argv[2], "rb") == 0)
+		use_texture = false;
+	else if (strcmp(argv[2], "tex") == 0)
+		use_texture = true;
+	else
+		print_usage_and_exit(argv[0]);
+
+	/* Detect parameter conflicts */
+	if (subtest == SUBTEST_SAMPLE && !use_texture) {
+		printf("Subtest 'sample' requires buffer_type 'tex'.\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* Requirements */
+	piglit_require_gl_version(11);
+	piglit_require_GLSL_version(110);
+	piglit_require_extension("GL_ARB_framebuffer_object");
+
+	/* Compile shaders */
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text);
+	fs_paint_red = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+						  fs_text_paint_red);
+	prog_paint_red = piglit_link_simple_program(vs, fs_paint_red);
+	if (!prog_paint_red)
+		piglit_report_result(PIGLIT_FAIL);
+	fs_sample = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					       fs_text_sample);
+	prog_sample = piglit_link_simple_program(vs, fs_sample);
+	if (!prog_sample)
+		piglit_report_result(PIGLIT_FAIL);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+
+	/* Set up framebuffer */
+	glGenFramebuffers(1, &fb);
+	glBindFramebuffer(GL_FRAMEBUFFER, fb);
+	if (use_texture) {
+		tex1 = allocate_texture();
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+				       GL_TEXTURE_2D, tex1, 0 /* level */);
+	} else {
+		GLuint rb;
+		glGenRenderbuffers(1, &rb);
+		glBindRenderbuffer(GL_RENDERBUFFER, rb);
+		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA,
+				      TEX_WIDTH, TEX_HEIGHT);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+					  GL_RENDERBUFFER, rb);
+	}
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+	fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+	if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Framebuffer status: %s\n",
+		       piglit_get_gl_enum_name(fb_status));
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* Set up second texture (used by "copy" test only) */
+	if (subtest == SUBTEST_COPY)
+		tex2 = allocate_texture();
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+	bool pass = true;
+	static const GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
+
+	/* Paint the texture red using a shader (not a fast clear). */
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
+	glUseProgram(prog_paint_red);
+	glViewport(0, 0, TEX_WIDTH, TEX_HEIGHT);
+	piglit_draw_rect(-1, -1, 2, 2);
+
+	/* Clear the texture to green; this will be optimized using
+	 * a fast color clear if the hardware is capable of it.
+	 */
+	glClearColor(0, 1, 0, 1);
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	switch (subtest) {
+	case SUBTEST_SAMPLE:
+		/* Sample from the texture and draw to the window
+		 * system framebuffer.
+		 */
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
+		glViewport(0, 0, piglit_width, piglit_height);
+		glUseProgram(prog_sample);
+		glUniform1i(glGetUniformLocation(prog_sample, "samp"), 0);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D, tex1);
+		piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo);
+		pass = piglit_probe_rect_rgba(0, 0, piglit_width,
+					      piglit_height, green) && pass;
+		break;
+	case SUBTEST_READ_PIXELS:
+		/* Read directly from the texture using
+		 * glReadPixels().
+		 */
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
+		pass = piglit_probe_rect_rgba(0, 0, TEX_WIDTH, TEX_HEIGHT,
+					      green) && pass;
+		/* And then clear the window system framebuffer to
+		 * black since there is nothing to display in this
+		 * subtest.
+		 */
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
+		glClearColor(0, 0, 0, 1);
+		glClear(GL_COLOR_BUFFER_BIT);
+		break;
+	case SUBTEST_BLIT:
+		/* Blit from the texture to the window system
+		 * fraembuffer.
+		 */
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
+		glBlitFramebuffer(0, 0, TEX_WIDTH, TEX_HEIGHT,
+				  0, 0, piglit_width, piglit_height,
+				  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo);
+		pass = piglit_probe_rect_rgba(0, 0, piglit_width,
+					      piglit_height, green) && pass;
+		break;
+	case SUBTEST_COPY:
+		/* Copy to a second texture using glCopyTexImage2D(). */
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
+		glBindTexture(GL_TEXTURE_2D, tex2);
+		glCopyTexImage2D(GL_TEXTURE_2D,
+				 0 /* level */,
+				 GL_RGBA,
+				 0, 0, TEX_WIDTH, TEX_HEIGHT,
+				 0 /* border */);
+		/* Sample from the second texture and draw to the
+		 * window system framebuffer.
+		 */
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
+		glViewport(0, 0, piglit_width, piglit_height);
+		glUseProgram(prog_sample);
+		glUniform1i(glGetUniformLocation(prog_sample, "samp"), 0);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D, tex2);
+		piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo);
+		pass = piglit_probe_rect_rgba(0, 0, piglit_width,
+					      piglit_height, green) && pass;
+		break;
+	}
+
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		pass = false;
+
+	piglit_present_results();
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
-- 
1.8.2.3



More information about the Piglit mailing list