[Piglit] [PATCH 4/4] framebuffer-blit-levels: Test stencil buffers.

Paul Berry stereotype441 at gmail.com
Wed Sep 5 14:59:34 PDT 2012


This patch modifies framebuffer-blit-levels to test that blitting
between miplevels of the stencil portion of a depth/stencil texture
works properly.  This is an important corner case for Mesa's i965
driver.

Note that since stencil data can't be uploaded to a texture using
glTexImage2D(), the test creates stencil test data by drawing directly
into the stencil buffer.
---
 tests/all.tests                                    |    2 +-
 .../framebuffer-blit-levels.c                      |  135 +++++++++++++++++---
 2 files changed, 116 insertions(+), 21 deletions(-)

diff --git a/tests/all.tests b/tests/all.tests
index 85f2691..abffc6d 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -1165,7 +1165,7 @@ 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 format in ('rgba', 'depth'):
+for format in ('rgba', 'depth', 'stencil'):
     for test_mode in ('draw', 'read'):
         test_name = ' '.join(['framebuffer-blit-levels', test_mode, format])
         arb_framebuffer_object[test_name] = PlainExecTest(test_name + ' -auto')
diff --git a/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c b/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c
index c605eba..3cb94c5 100644
--- a/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c
+++ b/tests/spec/arb_framebuffer_object/framebuffer-blit-levels.c
@@ -50,6 +50,9 @@
  *   and then using glReadPixels() on the auxiliary texture (this
  *   checks that blits work properly when GL_READ_FRAMEBUFFER is the
  *   test texture).
+ *
+ * Note: when testing a stencil texture, we don't use glTexImage2D()
+ * to upload data, since that doesn't work for stencil textures.
  */
 
 #include "piglit-util-gl-common.h"
@@ -125,16 +128,80 @@ create_test_data_depth(GLfloat *data, unsigned level,
 	}
 }
 
+/**
+ * Generate a block of test data appropriate for testing a stencil buffer.
+ *
+ * Note: since we can't use glTexImage2D() to upload stencil data,
+ * this function is only used to generate the "expected" stencil
+ * pattern when checking that the stencil data is correct; stencil
+ * data is uploaded using draw_test_data_stencil().  Accordingly we
+ * use a stencil pattern that is easy to draw: a pattern of concentric
+ * rectangles where the outermost rectangle has stencil value equal to
+ * the miplevel, the next inner rectangle has stencil value equal to
+ * miplevel+1, and so on.
+
+ */
+static void
+create_test_data_stencil(GLbyte *data, unsigned level,
+			 unsigned width, unsigned height)
+{
+	unsigned x, y;
+
+	for (y = 0; y < height; ++y) {
+		unsigned y_distance_to_edge = MIN2(y, height - 1 - y);
+		for (x = 0; x < width; ++x) {
+			unsigned x_distance_to_edge = MIN2(x, height - 1 - x);
+
+			data[y * width + x] = level + MIN2(x_distance_to_edge,
+							   y_distance_to_edge);
+		}
+	}
+}
+
+/**
+ * Use drawing operations to populate the stencil buffer with data
+ * equivalent to that generated by create_test_data_stencil().
+ */
+static void
+draw_test_data_stencil(unsigned level, unsigned width, unsigned height)
+{
+	unsigned i;
+	float xscale = 2.0 / width;
+	float yscale = 2.0 / height;
+
+	glViewport(0, 0, width, height);
+	glEnable(GL_STENCIL_TEST);
+
+	for (i = 0; 2 * i < MIN2(width, height); ++i) {
+		glStencilFunc(GL_ALWAYS, i + level, 0xff);
+		glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+		piglit_draw_rect(xscale * i - 1.0, yscale * i - 1.0,
+				 2.0 - 2.0 * xscale * i,
+				 2.0 - 2.0 * yscale * i);
+	}
+
+	glDisable(GL_STENCIL_TEST);
+}
+
 static void
 create_test_data(GLfloat *data, GLenum texture_format,
 		 unsigned level, unsigned width, unsigned height)
 {
-	if (texture_format == GL_RGBA)
+	switch (texture_format) {
+	case GL_RGBA:
 		create_test_data_rgba(data, level, width, height);
-	else if (texture_format == GL_DEPTH_COMPONENT)
+		break;
+	case GL_DEPTH_COMPONENT:
 		create_test_data_depth(data, level, width, height);
-	else
+		break;
+	case GL_DEPTH_STENCIL:
+		create_test_data_stencil((GLbyte *) data, level,
+					 width, height);
+		break;
+	default:
 		assert(0);
+		break;
+	}
 }
 
 static void
@@ -146,7 +213,8 @@ print_usage_and_exit(char *prog_name)
 	       "    read: test blitting *from* the given texture type\n"
 	       "  where <format> is one of:\n"
 	       "    rgba\n"
-	       "    depth\n",
+	       "    depth\n"
+	       "    stencil\n",
 	       prog_name);
 	piglit_report_result(PIGLIT_FAIL);
 }
@@ -180,6 +248,12 @@ piglit_init(int argc, char **argv)
 		texture_type = GL_FLOAT;
 		framebuffer_attachment = GL_DEPTH_ATTACHMENT;
 		blit_mask = GL_DEPTH_BUFFER_BIT;
+	} else if (strcmp(argv[2], "stencil") == 0) {
+		texture_internal_format = GL_DEPTH_STENCIL;
+		texture_format = GL_DEPTH_STENCIL;
+		texture_type = GL_UNSIGNED_INT_24_8;
+		framebuffer_attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+		blit_mask = GL_STENCIL_BUFFER_BIT;
 	} else {
 		print_usage_and_exit(argv[0]);
 	}
@@ -232,20 +306,43 @@ piglit_init(int argc, char **argv)
  * uploaded to.
  */
 static void
-upload_test_data(GLuint texture, unsigned data_level,
+upload_test_data(GLuint framebuffer, GLuint texture, unsigned data_level,
 		 unsigned upload_level, unsigned width, unsigned height)
 {
-	GLfloat *data = malloc(SIZE * SIZE * 4 * sizeof(GLfloat));
-
 	glBindTexture(GL_TEXTURE_2D, texture);
 
-	create_test_data(data, texture_format, data_level, width, height);
+	if (texture_format == GL_DEPTH_STENCIL) {
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+				       framebuffer_attachment,
+				       GL_TEXTURE_2D, texture, upload_level);
 
-	glTexImage2D(GL_TEXTURE_2D, upload_level, texture_internal_format,
-		     width, height, 0 /* border */, texture_format,
-		     texture_type, data);
+		draw_test_data_stencil(data_level, width, height);
+	} else {
+		GLfloat *data = malloc(SIZE * SIZE * 4 * sizeof(GLfloat));
 
-	free(data);
+		create_test_data(data, texture_format, data_level,
+				 width, height);
+
+		glTexImage2D(GL_TEXTURE_2D, upload_level,
+			     texture_internal_format,
+			     width, height, 0 /* border */, texture_format,
+			     texture_type, data);
+
+		free(data);
+	}
+}
+
+static bool
+test_image(unsigned width, unsigned height, const GLfloat *expected)
+{
+	if (texture_format == GL_DEPTH_STENCIL) {
+		return piglit_probe_image_stencil(0, 0, width, height,
+						  (const GLubyte *) expected);
+	} else {
+		return piglit_probe_image_color(0, 0, width, height,
+						texture_format, expected);
+	}
 }
 
 enum piglit_result
@@ -261,11 +358,13 @@ piglit_display()
 		unsigned height = SIZE >> level;
 		if (test_mode == TEST_MODE_READ) {
 			/* Populate directly */
-			upload_test_data(test_texture, level, level,
+			upload_test_data(test_framebuffer, test_texture,
+					 level, level,
 					 width, height);
 		} else {
 			/* Populate via aux texture */
-			upload_test_data(aux_texture, level, 0,
+			upload_test_data(aux_framebuffer, aux_texture,
+					 level, 0,
 					 width, height);
 			glBindFramebuffer(GL_READ_FRAMEBUFFER,
 					  aux_framebuffer);
@@ -297,9 +396,7 @@ piglit_display()
 					       GL_TEXTURE_2D,
 					       test_texture,
 					       level);
-			pass = piglit_probe_image_color(0, 0, width, height,
-							texture_format,
-							data) && pass;
+			pass = test_image(width, height, data) && pass;
 		} else {
 			/* Read via aux texture */
 			glBindFramebuffer(GL_READ_FRAMEBUFFER,
@@ -322,9 +419,7 @@ piglit_display()
 					  blit_mask, GL_NEAREST);
 			glBindFramebuffer(GL_READ_FRAMEBUFFER,
 					  aux_framebuffer);
-			pass = piglit_probe_image_color(0, 0, width, height,
-							texture_format,
-							data) && pass;
+			pass = test_image(width, height, data) && pass;
 		}
 	}
 
-- 
1.7.7.6



More information about the Piglit mailing list