[Piglit] [PATCH v3] EXT_multisampled_render_to_texture: functional test

Magnus Wendt magnus.wendt at intel.com
Wed Jan 13 06:37:57 PST 2016


EXT_multisampled_render_to_texture allows you to bind a singlesampled
texture to the color attachment of a multisampled framebuffer object.
Rendering is multisampled and the multisample data is implicitly
resolved and invalidated when texturing.

The test renders a ground truth image by drawing a slanted textured quad
to a multisampled fbo and resolves it using a blit to a singlesampled
fbo. This is textured onto the left half of the window.
It then renders the same thing into an implicitly resolved fbo and
textures that onto the right half of the screen. The two halfs are
compared. This is repeated for another slant and different clear colors
to check for possible interactions with fast clear.
The test passes if the two methods yeild identical results for all image
pairs.

v2: - Renamed main test and added api-errors and minmax tests.
    - Several minor changes mostly related to style. (Ian Romanick)
v3: - GLES3 error code overrides extension error code.

Signed-off-by: Magnus Wendt <magnus.wendt at intel.com>
---
 tests/all.py                                       |   9 +
 tests/spec/CMakeLists.txt                          |   1 +
 .../CMakeLists.gles3.txt                           |   7 +
 .../CMakeLists.txt                                 |   1 +
 .../api-errors.c                                   | 287 ++++++++++++++++
 .../ext_multisampled_render_to_texture/minmax.c    |  58 ++++
 .../ext_multisampled_render_to_texture/render.c    | 366 +++++++++++++++++++++
 7 files changed, 729 insertions(+)
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/api-errors.c
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/minmax.c
 create mode 100644 tests/spec/ext_multisampled_render_to_texture/render.c

diff --git a/tests/all.py b/tests/all.py
index 8982d22..1b3519b 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -4592,5 +4592,14 @@ with profile.group_manager(
     g(['arb_indirect_parameters-tf-count-arrays'], 'tf-count-arrays')
     g(['arb_indirect_parameters-tf-count-elements'], 'tf-count-elements')
 
+# Group EXT_multismapled_render_to_texture
+with profile.group_manager(
+        PiglitGLTest,
+        grouptools.join('spec', 'ext_multisampled_render_to_texture')) as g:
+    g(['ext_multisampled_render_to_texture-minmax'])
+    g(['ext_multisampled_render_to_texture-api-errors'])
+    for sample_count in (str(x) for x in MSAA_SAMPLE_COUNTS):
+        g(['ext_multisampled_render_to_texture-render', sample_count])
+
 if platform.system() is 'Windows':
     profile.filter_tests(lambda p, _: not p.startswith('glx'))
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index 383cd60..039323f 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -75,6 +75,7 @@ add_subdirectory (ext_depth_bounds_test)
 add_subdirectory (ext_fog_coord)
 add_subdirectory (ext_framebuffer_multisample)
 add_subdirectory (ext_framebuffer_multisample_blit_scaled)
+add_subdirectory (ext_multisampled_render_to_texture)
 add_subdirectory (ext_packed_depth_stencil)
 add_subdirectory (ext_packed_float)
 add_subdirectory (ext_shader_samples_identical)
diff --git a/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
new file mode 100644
index 0000000..4c7b02a
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.gles3.txt
@@ -0,0 +1,7 @@
+link_libraries(
+	piglitutil_${piglit_target_api}
+	)
+
+piglit_add_executable(ext_multisampled_render_to_texture-render render.c)
+piglit_add_executable(ext_multisampled_render_to_texture-api-errors api-errors.c)
+piglit_add_executable(ext_multisampled_render_to_texture-minmax minmax.c)
diff --git a/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/spec/ext_multisampled_render_to_texture/api-errors.c b/tests/spec/ext_multisampled_render_to_texture/api-errors.c
new file mode 100644
index 0000000..69f515d
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/api-errors.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2016 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 api-errors.c
+ *
+ * Input validation testing for EXT_multisampled_render_to_texture.
+ */
+
+#include "piglit-util-gl.h"
+
+#define FBO_HEIGHT (32)
+#define FBO_WIDTH (32)
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_es_version = 30;
+	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+enum piglit_result
+piglit_display(void)
+{
+	/* UNREACHED */
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLint max_samples = 0;
+	GLint max_renderbuffer_size = 0;
+	GLuint fbo, rb_depth, tex;
+	GLint samples_counts[20];
+	GLint num_samples_counts = 0;
+	bool pass = true;
+
+	piglit_require_extension("GL_EXT_multisampled_render_to_texture");
+
+	glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples);
+	glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
+
+	glGenFramebuffers(1, &fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+	/* glRenderbufferStorageMultisampleEXT */
+	glGenRenderbuffers(1, &rb_depth);
+	glBindRenderbuffer(GL_RENDERBUFFER, rb_depth);
+
+	/*
+	"If RenderbufferStorageMultisampleEXT is called with a value of
+	<samples> that is greater than MAX_SAMPLES_EXT, then the error
+	INVALID_VALUE is generated."
+	*/
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples+1,
+	                                    GL_DEPTH_COMPONENT16,
+	                                    FBO_WIDTH, FBO_HEIGHT);
+
+	if (piglit_get_gl_version() < 30) {
+		if (!piglit_check_gl_error(GL_INVALID_VALUE)) {
+			printf("glRenderbufferStorageMultisampleEXT w/ samples > "
+			       "GL_MAX_SAMPLES_EXT must emit GL_INVALID_VALUE but did not\n");
+			pass = false;
+		}
+	} else {
+		/*
+		OpenGL ES 3.0 and higher specifies a different error code for
+		glRenderbufferStorageMultisample. This should take presidence.
+		"An INVALID_OPERATION error is generated if <samples> is greater than the
+		maximum number of samples supported for <internalformat>"
+		*/
+		if (!piglit_check_gl_error(GL_INVALID_OPERATION)) {
+			printf("glRenderbufferStorageMultisample w/ samples > "
+			       "GL_MAX_SAMPLES_EXT must emit GL_INVALID_OPERATION but did not\n");
+			pass = false;
+		}
+	}
+
+	/*
+	"If either width or
+	height is greater than the value of MAX_RENDERBUFFER_SIZE, or if
+	samples is greater than the value of MAX_SAMPLES_EXT, then the error
+	INVALID_VALUE is generated. If OpenGL ES is unable to create a data
+	store of the requested size, the error OUT_OF_MEMORY is generated."
+	*/
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples,
+	                                    GL_DEPTH_COMPONENT16,
+	                                    max_renderbuffer_size+1, FBO_HEIGHT);
+
+	if (!piglit_check_gl_error(GL_INVALID_VALUE)) {
+		printf("glRenderbufferStorageMultisampleEXT w/ width > "
+		       "GL_MAX_RENDERBUFFER_SIZE must emit GL_INVALID_VALUE but did not\n");
+		pass = false;
+	}
+
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples,
+	                                    GL_DEPTH_COMPONENT16,
+	                                    FBO_WIDTH, max_renderbuffer_size+1);
+
+	if (!piglit_check_gl_error(GL_INVALID_VALUE)) {
+		printf("glRenderbufferStorageMultisampleEXT w/ height > "
+		       "GL_MAX_RENDERBUFFER_SIZE must emit GL_INVALID_VALUE but did not\n");
+		pass = false;
+	}
+
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples,
+	                                    GL_DEPTH_COMPONENT16,
+	                                    FBO_WIDTH, FBO_HEIGHT);
+
+	if (!piglit_check_gl_error(GL_NO_ERROR)) {
+		printf("An unexpected error has occured\n");
+		pass = false;
+	}
+
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+	                          GL_RENDERBUFFER, rb_depth);
+
+	/* glFramebufferTexture2DMultisampleEXT */
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, 0);
+
+	/*
+	"The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT
+	is called with a <target> that is not FRAMEBUFFER."
+	*/
+	glFramebufferTexture2DMultisampleEXT(GL_RENDERBUFFER,
+	                                     GL_COLOR_ATTACHMENT0,
+	                                     GL_TEXTURE_2D, tex, 0,
+	                                     max_samples);
+
+	if (!piglit_check_gl_error(GL_INVALID_ENUM)) {
+		printf("glFramebufferTexture2DMultisampleEXT w/ <target> != "
+		       "GL_FRAMEBUFFER must emit GL_INVALID_ENUM but did not\n");
+		pass = false;
+	}
+
+	/*
+	"The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT
+	is called with an <attachment> that is not COLOR_ATTACHMENT0."
+	*/
+	glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+	                                     GL_DEPTH_ATTACHMENT,
+	                                     GL_TEXTURE_2D, tex, 0,
+	                                     max_samples);
+
+	if (!piglit_check_gl_error(GL_INVALID_ENUM)) {
+		printf("glFramebufferTexture2DMultisampleEXT w/ <attachment> != "
+		       "GL_COLOR_ATTACHMENT0 must emit GL_INVALID_ENUM but did not\n");
+		pass = false;
+	}
+
+	/*
+	"The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT
+	is called with a <textarget> that is not TEXTURE_2D,
+	TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y,
+	TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_X,
+	TEXTURE_CUBE_MAP_NEGATIVE_Y, or TEXTURE_CUBE_MAP_NEGATIVE_Z."
+	*/
+	glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+	                                     GL_COLOR_ATTACHMENT0,
+	                                     GL_TEXTURE_2D_MULTISAMPLE, tex, 0,
+	                                     max_samples);
+
+	if (!piglit_check_gl_error(GL_INVALID_ENUM)) {
+		printf("glFramebufferTexture2DMultisampleEXT w/ <textarget> != GL_TEXTURE_2D,\n"
+		       "GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,\n"
+		       "GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,\n"
+		       "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z\n"
+		       "must emit GL_INVALID_ENUM but did not\n");
+		pass = false;
+	}
+
+	glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+	                                     GL_COLOR_ATTACHMENT0,
+	                                     GL_TEXTURE_2D, tex, 0,
+	                                     max_samples);
+
+	if (!piglit_check_gl_error(GL_NO_ERROR)) {
+		printf("An unexpected error has occured\n");
+		pass = false;
+	}
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Framebuffer is incomplete");
+		pass = false;
+	}
+
+	/*
+	"Otherwise samples represents a request for a desired minimum number
+	of samples. Since different implementations may support different
+	sample counts for multisampled rendering, the actual number of samples
+	allocated for the image is implementation-dependent. However, the
+	resulting value for TEXTURE_SAMPLES_EXT is guaranteed to be greater
+	than or equal to samples and no more than the next larger sample count
+	supported by the implementation."
+	*/
+	glGetInternalformativ(GL_RENDERBUFFER,
+	                      GL_RGB8,
+	                      GL_SAMPLES,
+	                      ARRAY_SIZE(samples_counts),
+	                      &samples_counts[0]);
+
+	glGetInternalformativ(GL_RENDERBUFFER,
+	                      GL_RGB8,
+	                      GL_NUM_SAMPLE_COUNTS,
+	                      1,
+	                      &num_samples_counts);
+
+	/* also test with samples == 0 */
+	assert(num_samples_counts < ARRAY_SIZE(samples_counts));
+	samples_counts[num_samples_counts] = 0;
+	num_samples_counts++;
+
+	for (int requested_samples = 0; requested_samples <= max_samples; requested_samples++) {
+
+		int expected_samples = 0;
+		int actual_tex_samples = 0;
+		int actual_depth_samples = 0;
+		for (int i = 0; i < num_samples_counts; i++) {
+			if (samples_counts[i] >= requested_samples)
+				expected_samples = samples_counts[i];
+			else
+				break;
+		}
+
+		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, requested_samples,
+		                                    GL_DEPTH_COMPONENT16,
+		                                    FBO_WIDTH, FBO_HEIGHT);
+		glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+		                                     GL_COLOR_ATTACHMENT0,
+		                                     GL_TEXTURE_2D, tex, 0,
+		                                     requested_samples);
+
+		glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+		                             GL_RENDERBUFFER_SAMPLES_EXT,
+		                             &actual_depth_samples);
+
+		if (actual_depth_samples != expected_samples) {
+			printf("glRenderbufferStorageMultisampleEXT requested %d samples, "
+			       "expected %d samples, but got %d samples\n",
+			       requested_samples, expected_samples, actual_depth_samples);
+			pass = false;
+		}
+
+		glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
+		                                      GL_COLOR_ATTACHMENT0,
+		                                      GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT,
+		                                      &actual_tex_samples);
+
+		if (actual_tex_samples != expected_samples) {
+			printf("glFramebufferTexture2DMultisampleEXT requested %d samples, "
+			       "expected %d samples, but got %d samples\n",
+			       requested_samples, expected_samples, actual_tex_samples);
+			pass = false;
+		}
+
+		if (!piglit_check_gl_error(GL_NO_ERROR)) {
+			printf("An unexpected error has occured\n");
+			pass = false;
+		}
+	}
+
+	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
\ No newline at end of file
diff --git a/tests/spec/ext_multisampled_render_to_texture/minmax.c b/tests/spec/ext_multisampled_render_to_texture/minmax.c
new file mode 100644
index 0000000..1cfbf22
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/minmax.c
@@ -0,0 +1,58 @@
+/* Copyright (c) 2016 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 minmax.c
+ *
+ * Test for the minimum maximum values in GL_EXT_multisampled_render_to_texture.
+ */
+
+#include "piglit-util-gl.h"
+#include "minmax-test.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_es_version = 20;
+	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+enum piglit_result
+piglit_display(void)
+{
+	/* UNREACHED */
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	piglit_print_minmax_header();
+
+	piglit_require_extension("GL_EXT_multisampled_render_to_texture");
+
+	piglit_test_min_int(GL_MAX_SAMPLES_EXT, 2);
+
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+
+	piglit_report_result(piglit_minmax_pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
diff --git a/tests/spec/ext_multisampled_render_to_texture/render.c b/tests/spec/ext_multisampled_render_to_texture/render.c
new file mode 100644
index 0000000..c097862
--- /dev/null
+++ b/tests/spec/ext_multisampled_render_to_texture/render.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2016 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 render.c
+ * Functional test for EXT_multisampled_render_to_texture.
+ *
+ * The test renders a ground truth image by drawing a slanted textured quad
+ * to a multisampled fbo and resolves it using a blit to a singlesampled fbo.
+ * This is textured onto the left half of the window.
+ * It then renders the same thing into an implicitly resolved fbo and textures
+ * that onto the right half of the screen. The two halfs are compared. This is
+ * repeated for another slant and different clear colors to check for possible
+ * interactions with fast clear.
+ * The test passes if the two methods yeild identical results for all image
+ * pairs.
+ *
+ */
+
+#include "piglit-util-gl.h"
+
+#define TEX_HEIGHT (8)
+#define TEX_WIDTH (8)
+#define FBO_HEIGHT (32)
+#define FBO_WIDTH (32)
+#define FB_HEIGHT (64)
+#define FB_WIDTH (2*FB_HEIGHT)
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+	/* multisampled FBO used for ground truth req ES 3.0 */
+	config.supports_gl_es_version = 30;
+	config.window_visual = PIGLIT_GL_VISUAL_RGB
+	                     | PIGLIT_GL_VISUAL_DOUBLE;
+	config.window_width  = FB_WIDTH;
+	config.window_height = FB_HEIGHT;
+PIGLIT_GL_TEST_CONFIG_END
+
+#define SOURCE(x) # x
+static const GLchar vshader_src[] = "#version 100\n" SOURCE(
+	attribute vec4 piglit_vertex;
+	attribute vec2 piglit_texcoord;
+	varying vec2 coord_fs;
+
+	void main()
+	{
+		gl_Position =  piglit_vertex;
+		coord_fs = piglit_texcoord;
+	}
+);
+
+static const GLchar fshader_src[] = "#version 100\n" SOURCE(
+	precision highp float;
+	varying vec2 coord_fs;
+	uniform sampler2D tex;
+
+	void main()
+	{
+		gl_FragColor = texture2D(tex, coord_fs);
+	}
+);
+
+static GLuint tex_check;
+
+static struct {
+	GLuint fbo;
+	GLuint color;
+	GLuint depth;
+} fbo_ms, fbo_ss, fbo_impl;
+
+static GLuint basic_tex_prog, tex_loc;
+
+static GLubyte tex_data[TEX_HEIGHT][TEX_WIDTH][3];
+
+static void gen_texdata(void)
+{
+	int x,y;
+	for (y = 0; y < TEX_HEIGHT; ++y) {
+		for (x = 0; x < TEX_WIDTH; ++x) {
+			tex_data[y][x][0] = (GLubyte) (255.0f *
+			                    ((float)x/(float)(TEX_WIDTH-1)));
+			tex_data[y][x][1] = (GLubyte) (255.0f *
+			                    ((float)y/(float)(TEX_HEIGHT-1)));
+			tex_data[y][x][2] = 127;
+		}
+	}
+	for (y = 0; y < TEX_HEIGHT; ++y) {
+		for (x = 0; x < TEX_WIDTH; ++x) {
+			if ((x^y)&1) {
+				tex_data[y][x][0] /= 2;
+				tex_data[y][x][1] /= 2;
+				tex_data[y][x][2] = 64;
+			}
+		}
+	}
+}
+
+enum piglit_result
+piglit_display(void)
+{
+	bool pass = true;
+
+	static const GLfloat const quad1_verts[4][4] = {
+		{ -0.7,  -0.9, 0, 1 },
+		{  0.9,  -0.7, 0, 1 },
+		{ -0.9,   0.7, 0, 1 },
+		{  0.7,   0.9, 0, 1 },
+	};
+
+	static const GLfloat const quad2_verts[4][4] = {
+		{ -0.9,  -0.7, 0, 1 },
+		{  0.7,  -0.9, 0, 1 },
+		{ -0.7,   0.9, 0, 1 },
+		{  0.9,   0.7, 0, 1 },
+	};
+
+	static const GLfloat const tex_coords[4][2] = {
+		{ 0.0, 0.0 },
+		{ 1.0, 0.0 },
+		{ 0.0, 1.0 },
+		{ 1.0, 1.0 },
+	};
+
+	static const GLfloat const white[] = {1.0, 1.0, 1.0, 1.0};
+	static const GLfloat const gray[] = {0.5, 0.5, 0.5, 0.0};
+
+	/* Run the test in multiple passes with different geometry and
+	 * different clear colors to catch possible interactions with fast
+	 * clear.
+	 */
+	static const GLfloat const *test_config[4][2] = {
+		{ gray,  &quad1_verts[0][0] },
+		{ gray,  &quad2_verts[0][0] },
+		{ white, &quad1_verts[0][0] },
+		{ white, &quad2_verts[0][0] }
+	};
+
+	for (int i = 0; i < ARRAY_SIZE(test_config); i++) {
+		GLfloat const *clear_color = test_config[i][0];
+		GLfloat const *quad_verts  = test_config[i][1];
+		glClearColor(clear_color[0], clear_color[1],
+		             clear_color[2], clear_color[3]);
+		glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
+		glClear(GL_COLOR_BUFFER_BIT);
+		/*** Explicit Resolve (ground truth) ***/
+		/* Draw quad into MS renderbuffer */
+		glBindFramebuffer(GL_FRAMEBUFFER, fbo_ms.fbo);
+		glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glBindTexture(GL_TEXTURE_2D, tex_check);
+		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
+
+		/* Do the explicit multisample resolve */
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_ms.fbo);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_ss.fbo);
+		glBlitFramebuffer(0, 0, FBO_WIDTH, FBO_HEIGHT,
+		                  0, 0, FBO_WIDTH, FBO_HEIGHT,
+		                  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+		/* draw the result to the left side of the frame buffer */
+		glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
+		glViewport(0, 0, FB_WIDTH/2, FB_HEIGHT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glBindTexture(GL_TEXTURE_2D, fbo_ss.color);
+		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
+
+		pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+
+		/*** Implicit Resolve ***/
+		/* Draw quad into MSAA texture */
+		glBindFramebuffer(GL_FRAMEBUFFER, fbo_impl.fbo);
+		glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+		glBindTexture(GL_TEXTURE_2D, tex_check);
+		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
+
+		/* draw the result to the right side of the frame buffer */
+		glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
+		glViewport(FB_WIDTH/2, 0, FB_WIDTH/2, FB_HEIGHT);
+
+		glBindTexture(GL_TEXTURE_2D, fbo_impl.color);
+		piglit_draw_rect_from_arrays(quad_verts, tex_coords, false);
+
+		/*** Compare the results ***/
+		if (!piglit_probe_rect_halves_equal_rgba(0, 0, FB_WIDTH,
+		                                         FB_HEIGHT)) {
+			pass = false;
+			printf("Test failed during pass %d\n", i);
+		}
+
+		piglit_present_results();
+
+		/* The test has failed, so there is no point in continuing.
+		 * Break so that the failure isn't overdrawn.
+		 */
+		if (!pass)
+			break;
+	}
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+	int samples = 0, samples_impl = 0, samples_expl = 0;
+
+	GLint max_samples;
+
+	piglit_require_extension("GL_EXT_multisampled_render_to_texture");
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s <sample_count>\n", argv[0]);
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	samples = strtoul(argv[1], NULL, 0);
+	glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+	if (samples > max_samples) {
+		piglit_report_result(PIGLIT_SKIP);
+	}
+
+	/* Create primary texture */
+	gen_texdata();
+	glGenTextures(1, &tex_check);
+	glActiveTexture( GL_TEXTURE0 );
+	glBindTexture(GL_TEXTURE_2D, tex_check);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, tex_data);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+	/* Create multisampled FBO for explicit resolve (ground truth) */
+	glGenFramebuffers(1, &fbo_ms.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo_ms.fbo);
+
+	/* depth */
+	glGenRenderbuffers(1, &fbo_ms.depth);
+	glBindRenderbuffer(GL_RENDERBUFFER, fbo_ms.depth);
+	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+	                                 GL_DEPTH_COMPONENT16,
+	                                 FBO_WIDTH, FBO_HEIGHT);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+	                          GL_RENDERBUFFER, fbo_ms.depth);
+
+	/* color */
+	glGenRenderbuffers(1, &fbo_ms.color);
+	glBindRenderbuffer(GL_RENDERBUFFER, fbo_ms.color);
+	glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGB8,
+	                                 FBO_WIDTH, FBO_HEIGHT);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+	                          GL_RENDERBUFFER, fbo_ms.color);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Multisampled framebuffer is incomplete");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
+	                             &samples_expl);
+
+	/* Create singlesampled FBO for explicit resolve (ground truth) */
+	glGenFramebuffers(1, &fbo_ss.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo_ss.fbo);
+
+	/* color */
+	glGenTextures(1, &fbo_ss.color);
+	glBindTexture(GL_TEXTURE_2D, fbo_ss.color);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, 0);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+	                       GL_TEXTURE_2D, fbo_ss.color, 0);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Singlesampled framebuffer is incomplete");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* Create FBO for implicit resolve */
+	glGenFramebuffers(1, &fbo_impl.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo_impl.fbo);
+
+	/* depth */
+	glGenRenderbuffers(1, &fbo_impl.depth);
+	glBindRenderbuffer(GL_RENDERBUFFER, fbo_impl.depth);
+	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
+	                                    GL_DEPTH_COMPONENT16,
+	                                    FBO_WIDTH, FBO_HEIGHT);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+	                          GL_RENDERBUFFER, fbo_impl.depth);
+
+	/* color */
+	glGenTextures(1, &fbo_impl.color);
+	glBindTexture(GL_TEXTURE_2D, fbo_impl.color);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, FBO_WIDTH, FBO_HEIGHT, 0,
+	             GL_RGB, GL_UNSIGNED_BYTE, 0);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+	                                     GL_COLOR_ATTACHMENT0,
+	                                     GL_TEXTURE_2D, fbo_impl.color, 0,
+	                                     samples);
+
+	if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
+	                          != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Implicitly resolved multisampled framebuffer is incomplete");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
+			GL_COLOR_ATTACHMENT0,
+			GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT,
+			&samples_impl);
+
+	glDisable(GL_CULL_FACE);
+	glEnable(GL_DEPTH_TEST);
+
+	/* Test that we get the same number of samples for the two methods */
+
+	if (samples_impl != samples_expl) {
+		printf("samples_expl: %d, samples_impl: %d\n",
+		        samples_expl, samples_impl);
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	/* create basic texturing shader */
+	basic_tex_prog = piglit_build_simple_program(vshader_src,
+	                                             fshader_src);
+	glUseProgram(basic_tex_prog);
+	tex_loc = glGetUniformLocation(basic_tex_prog, "tex");
+
+	if (!piglit_check_gl_error(GL_NO_ERROR)) {
+		piglit_report_result(PIGLIT_FAIL);
+	}
+}
-- 
2.5.0



More information about the Piglit mailing list