[Piglit] [PATCH] Test that glBlitFramebuffer works properly with nonzero miplevels.

Paul Berry stereotype441 at gmail.com
Tue Aug 14 13:23:07 PDT 2012


This patch adds a test to verify the proper operation of
glBlitFramebuffer when blitting to and from miplevels other than zero.
---
 tests/all.tests                                    |    3 +
 .../spec/arb_framebuffer_object/CMakeLists.gl.txt  |    1 +
 .../framebuffer-blit-levels.c                      |  250 ++++++++++++++++++++
 3 files changed, 254 insertions(+), 0 deletions(-)
 create mode 100644 tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c

diff --git a/tests/all.tests b/tests/all.tests
index 9419e73..a03b904 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -1163,6 +1163,9 @@ spec['ARB_framebuffer_object'] = arb_framebuffer_object
 add_concurrent_test(arb_framebuffer_object, 'same-attachment-glFramebufferTexture2D-GL_DEPTH_STENCIL_ATTACHMENT')
 add_concurrent_test(arb_framebuffer_object, 'same-attachment-glFramebufferRenderbuffer-GL_DEPTH_STENCIL_ATTACHMENT')
 add_plain_test(arb_framebuffer_object, 'fdo28551')
+for test_mode in ('draw', 'read'):
+        test_name = ' '.join(['framebuffer-blit-levels', test_mode])
+        arb_framebuffer_object[test_name] = PlainExecTest(test_name + ' -auto')
 
 
 # Group ARB_sampler_objects
diff --git a/tests/spec/arb_framebuffer_object/CMakeLists.gl.txt b/tests/spec/arb_framebuffer_object/CMakeLists.gl.txt
index 9764bf3..33b09c1 100644
--- a/tests/spec/arb_framebuffer_object/CMakeLists.gl.txt
+++ b/tests/spec/arb_framebuffer_object/CMakeLists.gl.txt
@@ -10,6 +10,7 @@ link_libraries (
 	${OPENGL_glu_LIBRARY}
 )
 
+piglit_add_executable(framebuffer-blit-levels framebuffer-blit-levels.c)
 piglit_add_executable(get-renderbuffer-internalformat get-renderbuffer-internalformat.c)
 piglit_add_executable(same-attachment-glFramebufferTexture2D-GL_DEPTH_STENCIL_ATTACHMENT same-attachment-glFramebufferTexture2D-GL_DEPTH_STENCIL_ATTACHMENT.c)
 piglit_add_executable(same-attachment-glFramebufferRenderbuffer-GL_DEPTH_STENCIL_ATTACHMENT same-attachment-glFramebufferRenderbuffer-GL_DEPTH_STENCIL_ATTACHMENT.c)
diff --git a/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c b/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c
new file mode 100644
index 0000000..31e0cf2
--- /dev/null
+++ b/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright © 2012 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 framebuffer-blit-levels.c
+ *
+ * This test verifies that glBlitFramebuffer operates correctly when
+ * the read or draw framebuffer is bound to a nonzero miplevel of a
+ * texture.
+ *
+ * The test can be run in two modes: "read" and "draw".  In "read"
+ * mode, the layered/mipmapped texture is attached to
+ * GL_READ_FRAMEBUFFER, and in "draw" mode, the layered/mipmapped
+ * texture is attached to GL_DRAW_FRAMEBUFFER.
+ *
+ * The test operates as follows:
+ *
+ * - A 2D test texture is created with all miplevels present.  An
+ *   auxiliary 2D texture is also created which has a single miplevel.
+ *
+ * - The test texture is populated with a deterministic pattern of
+ *   data.  In "read" mode, this is done by simply uploading the data
+ *   pattern using glTexImage2D.  In "draw" mode, this is done by
+ *   first uploading the data pattern to the auxiliary texture, and
+ *   then blitting it to the test texture (this checks that blits work
+ *   properly when GL_DRAW_FRAMEBUFFER is the test texture).
+ *
+ * - The data in the test texture is then verified.  In "draw" mode,
+ *   this is done by a direct call to glReadPixels().  In "read" mode,
+ *   this is done by first blitting the data to the auxiliary texture,
+ *   and then using glReadPixels() on the auxiliary texture (this
+ *   checks that blits work properly when GL_READ_FRAMEBUFFER is the
+ *   test texture).
+ */
+
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_MAIN(
+    32,
+    32,
+    GLUT_RGBA);
+
+enum {
+	TEST_MODE_DRAW,
+	TEST_MODE_READ,
+} test_mode;
+
+GLuint test_framebuffer;
+GLuint aux_framebuffer;
+
+GLuint test_texture;
+GLuint aux_texture;
+
+#define LOG2_SIZE 7
+#define SIZE (1 << LOG2_SIZE)
+
+/**
+ * Generate a block of test data in which each pixel has a unique RGBA
+ * color.  Different values of the \c level parameter produce
+ * different unique sets of pixels.
+ *
+ * This takes advantage of the Chinese Remainder Theorem to produce a
+ * unique color for each pixel--we produce the R, G, B, and A values
+ * by taking an integer mod four different primes.
+ */
+static void
+create_test_data(GLfloat *data, unsigned level,
+		 unsigned width, unsigned height)
+{
+	unsigned pixel;
+	unsigned num_pixels = width * height;
+	for (pixel = 0; pixel < num_pixels; ++pixel) {
+		unsigned unique_value = level * (SIZE * SIZE) + pixel;
+		data[4*pixel + 0] = (unique_value % 233) / 233.0;
+		data[4*pixel + 1] = (unique_value % 239) / 239.0;
+		data[4*pixel + 2] = (unique_value % 241) / 241.0;
+		data[4*pixel + 3] = (unique_value % 251) / 251.0;
+	}
+}
+
+static void
+print_usage_and_exit(char *prog_name)
+{
+	printf("Usage: %s <test_mode>\n"
+	       "  where <test_mode> is one of:\n"
+	       "    draw: test blitting *to* the given texture type\n"
+	       "    read: test blitting *from* the given texture type\n",
+	       prog_name);
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	unsigned level;
+
+	if (argc != 2) {
+		print_usage_and_exit(argv[0]);
+	}
+
+	if (strcmp(argv[1], "draw") == 0) {
+		test_mode = TEST_MODE_DRAW;
+	} else if (strcmp(argv[1], "read") == 0) {
+		test_mode = TEST_MODE_READ;
+	} else {
+		print_usage_and_exit(argv[0]);
+	}
+
+	piglit_require_extension("GL_ARB_framebuffer_object");
+
+	/* Set up test framebuffer and test texture, but don't
+	 * populate with data yet.
+	 */
+	glGenFramebuffers(1, &test_framebuffer);
+	glGenTextures(1, &test_texture);
+	glBindTexture(GL_TEXTURE_2D, test_texture);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+			GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+			GL_NEAREST);
+	for (level = 0; level < LOG2_SIZE; ++level) {
+		glTexImage2D(GL_TEXTURE_2D, level,
+			     GL_RGBA, SIZE >> level, SIZE >> level,
+			     0 /* border */, GL_RGBA,
+			     GL_BYTE /* type */, NULL /* data */);
+	}
+
+	/* Set up aux framebuffer */
+	glGenFramebuffers(1, &aux_framebuffer);
+	glGenTextures(1, &aux_texture);
+	glBindTexture(GL_TEXTURE_2D, aux_texture);
+	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, SIZE, SIZE,
+		     0 /* border */, GL_RGBA,
+		     GL_BYTE /* type */, NULL /* data */);
+	glBindFramebuffer(GL_FRAMEBUFFER, aux_framebuffer);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+			       GL_TEXTURE_2D, aux_texture, 0 /* level */);
+}
+
+enum piglit_result
+piglit_display()
+{
+	bool pass = true;
+	GLfloat *data = malloc(SIZE * SIZE * 4 * sizeof(GLfloat));
+	unsigned level;
+
+	/* Populate the test texture */
+	for (level = 0; level < LOG2_SIZE; ++level) {
+		unsigned width = SIZE >> level;
+		unsigned height = SIZE >> level;
+		create_test_data(data, level, width, height);
+		if (test_mode == TEST_MODE_READ) {
+			/* Populate directly */
+			glBindTexture(GL_TEXTURE_2D, test_texture);
+			glTexImage2D(GL_TEXTURE_2D, level,
+				     GL_RGBA, width, height,
+				     0 /* border */, GL_RGBA,
+				     GL_FLOAT /* type */, data);
+		} else {
+			/* Populate via aux texture */
+			glBindFramebuffer(GL_READ_FRAMEBUFFER,
+					  aux_framebuffer);
+			glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
+					  test_framebuffer);
+			glBindTexture(GL_TEXTURE_2D, aux_texture);
+			glTexImage2D(GL_TEXTURE_2D, 0 /* level */,
+				     GL_RGBA, width, height,
+				     0 /* border */, GL_RGBA,
+				     GL_FLOAT /* type */, data);
+			glBindTexture(GL_TEXTURE_2D, test_texture);
+			glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+					       GL_COLOR_ATTACHMENT0,
+					       GL_TEXTURE_2D,
+					       test_texture,
+					       level);
+			glBlitFramebuffer(0, 0, width, height,
+					  0, 0, width, height,
+					  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+		}
+	}
+
+	/* Verify the test texture */
+	for (level = 0; level < LOG2_SIZE; ++level) {
+		unsigned width = SIZE >> level;
+		unsigned height = SIZE >> level;
+		printf("Testing level %d\n", level);
+		create_test_data(data, level, width, height);
+		if (test_mode == TEST_MODE_DRAW) {
+			/* Read texture data directly using glReadPixels() */
+			glBindFramebuffer(GL_READ_FRAMEBUFFER, test_texture);
+			glFramebufferTexture2D(GL_READ_FRAMEBUFFER,
+					       GL_COLOR_ATTACHMENT0,
+					       GL_TEXTURE_2D,
+					       test_texture,
+					       level);
+			pass = piglit_probe_image_rgba(0, 0, width, height,
+						       data) && pass;
+		} else {
+			/* Read via aux texture */
+			glBindFramebuffer(GL_READ_FRAMEBUFFER,
+					  test_framebuffer);
+			glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
+					  aux_framebuffer);
+			glBindTexture(GL_TEXTURE_2D, test_texture);
+			glFramebufferTexture2D(GL_READ_FRAMEBUFFER,
+					       GL_COLOR_ATTACHMENT0,
+					       GL_TEXTURE_2D,
+					       test_texture,
+					       level);
+			glBindTexture(GL_TEXTURE_2D, aux_texture);
+			glTexImage2D(GL_TEXTURE_2D, 0 /* level */,
+				     GL_RGBA, width, height,
+				     0 /* border */, GL_RGBA,
+				     GL_BYTE /* type */, NULL);
+			glBlitFramebuffer(0, 0, width, height,
+					  0, 0, width, height,
+					  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+			glBindFramebuffer(GL_READ_FRAMEBUFFER,
+					  aux_framebuffer);
+			pass = piglit_probe_image_rgba(0, 0, width, height,
+						       data) && pass;
+		}
+	}
+
+	free(data);
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
-- 
1.7.7.6



More information about the Piglit mailing list