[Piglit] [PATCH] fbo-blit-after-swap: New test for partial blits after a buffer swap

Ian Romanick idr at freedesktop.org
Wed Oct 30 19:48:47 CET 2013


On 10/29/2013 01:19 PM, Federico Mena Quintero wrote:
> From: Federico Mena Quintero <federico at suse.com>
> 
> The clutter/cogl libraries try to minimize the area that gets updated on every frame.
> They do this by doing glBlitFramebufferEXT() from the back buffer to the front buffer.
> 
> However, this is buggy with software rendering if there has been a buffer swap
> *before* the first blit from the back buffer to the front buffer.  In this case,
> Mesa copies the whole back buffer into the front buffer, instead of just the
> requested region.
> ---
>  tests/all.tests                 |   1 +
>  tests/fbo/CMakeLists.gl.txt     |   1 +
>  tests/fbo/fbo-blit-after-swap.c | 136 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 138 insertions(+)
>  create mode 100644 tests/fbo/fbo-blit-after-swap.c
> 
> diff --git a/tests/all.tests b/tests/all.tests
> index 7ab841e..6c92ebf 100644
> --- a/tests/all.tests
> +++ b/tests/all.tests
> @@ -1163,6 +1163,7 @@ for format in ('rgba', 'depth', 'stencil'):
>          test_name = ' '.join(['framebuffer-blit-levels', test_mode, format])
>          arb_framebuffer_object[test_name] = PlainExecTest(test_name + ' -auto')
>  add_plain_test(arb_framebuffer_object, 'fbo-alpha')
> +add_plain_test(arb_framebuffer_object, 'fbo-blit-after-swap')
>  add_plain_test(arb_framebuffer_object, 'fbo-blit-stretch')
>  add_plain_test(arb_framebuffer_object, 'fbo-blit-scaled-linear')
>  add_plain_test(arb_framebuffer_object, 'fbo-attachments-blit-scaled-linear')
> diff --git a/tests/fbo/CMakeLists.gl.txt b/tests/fbo/CMakeLists.gl.txt
> index 588fe26..3ad9ec0 100644
> --- a/tests/fbo/CMakeLists.gl.txt
> +++ b/tests/fbo/CMakeLists.gl.txt
> @@ -31,6 +31,7 @@ piglit_add_executable (fbo-alpha fbo-alpha.c)
>  piglit_add_executable (fbo-luminance-alpha fbo-luminance-alpha.c)
>  piglit_add_executable (fbo-bind-renderbuffer fbo-bind-renderbuffer.c)
>  piglit_add_executable (fbo-blit fbo-blit.c)
> +piglit_add_executable (fbo-blit-after-swap fbo-blit-after-swap.c)
>  piglit_add_executable (fbo-blit-d24s8 fbo-blit-d24s8.c)
>  piglit_add_executable (fbo-blit-stretch fbo-blit-stretch.cpp)
>  piglit_add_executable (fbo-blending-formats fbo-blending-formats.c)
> diff --git a/tests/fbo/fbo-blit-after-swap.c b/tests/fbo/fbo-blit-after-swap.c
> new file mode 100644
> index 0000000..38fc870
> --- /dev/null
> +++ b/tests/fbo/fbo-blit-after-swap.c
> @@ -0,0 +1,136 @@
> +/*
> + * Copyright 2013 Suse, Inc. 
> + * Copyright © 2011 Henri Verbeet <hverbeet at gmail.com>
> + * Copyright 2011 Red Hat, Inc.
> + *
> + * 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 fbo-blit-after-swap.c
> + *
> + * Test a glBlitFrameBuffer() with a smaller-than-the-window region after doing a buffer swap
> + */
> +
> +#include "piglit-util-gl-common.h"
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +	config.supports_gl_compat_version = 10;
> +
> +	config.window_width = 128;
> +	config.window_height = 128;

Does the test need a non-default size?  The rest of the test code
appears to adapt to any window size.

> +	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
> +	config.requires_displayed_window = true;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +#define SWAP_BUFFERS_BEFORE_BLIT 1
> +
> +static const float red[]   = {1.0f, 0.0f, 0.0f, 1.0f};
> +static const float blue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
> +static const float black[] = {0.0f, 0.0f, 0.0f, 1.0f};
> +
> +static void
> +setup_front_buffer(void)
> +{
> +	glDrawBuffer(GL_BACK);
> +
> +	glClearColor(blue[0], blue[1], blue[2], blue[3]);
> +	glClear(GL_COLOR_BUFFER_BIT);
> +
> +#if SWAP_BUFFERS_BEFORE_BLIT

Ideally, the test binary should be able to do both these things based on
a commandline parameter.

> +	piglit_swap_buffers();
> +#else
> +	glDrawBuffer(GL_FRONT);
> +	glReadBuffer(GL_BACK);
> +	glBlitFramebufferEXT(0, 0, piglit_width, piglit_height,
> +			     0, 0, piglit_width, piglit_height,
> +			     GL_COLOR_BUFFER_BIT, GL_NEAREST);
> +#endif
> +}
> +
> +static void
> +setup_back_buffer(void)
> +{
> +	int w = piglit_width;
> +	int h = piglit_height;
> +
> +	glDrawBuffer(GL_BACK);
> +
> +	/* Clear to black */
> +	glClearColor(black[0], black[1], black[2], black[3]);
> +	glClear(GL_COLOR_BUFFER_BIT);
> +
> +	/* Paint a red square in the middle of the back buffer */
> +	glColor4f(red[0], red[1], red[2], red[3]);

    glColor4fv(red);

> +	piglit_draw_rect(w / 4, h / 4, w / 2, h / 2);
> +}
> +
> +static void
> +blit_from_back_to_front(void)
> +{
> +	int w = piglit_width;
> +	int h = piglit_height;
> +
> +	/* Copy just the red square from the back buffer to the blue front buffer */
> +	glDrawBuffer(GL_FRONT);
> +	glReadBuffer(GL_BACK);
> +	glBlitFramebufferEXT(w / 4, h / 4, 3 * w / 4, 3 * h / 4,
> +			     w / 4, h / 4, 3 * w / 4, 3 * h / 4,
> +			     GL_COLOR_BUFFER_BIT, GL_NEAREST);
> +}
> +
> +enum piglit_result piglit_display(void)
> +{
> +	int w = piglit_width;
> +	int h = piglit_height;
> +	bool success = 1;

    bool pass = true;

> +
> +	piglit_ortho_projection(w, h, GL_FALSE);
> +
> +	setup_front_buffer();
> +	setup_back_buffer();
> +
> +	blit_from_back_to_front();
> +
> +	glFlush();
> +
> +	/* Now see how we did... */
> +
> +	glReadBuffer(GL_FRONT);
> +
> +	/* the middle should be red */
> +	success &= piglit_probe_pixel_rgb(w / 2, h / 2, red);
> +
> +	/* the corners should be blue */
> +	success &= piglit_probe_pixel_rgb(0, 0, blue);

The correct idiom is:

        pass = ... && pass;

As written, once pass is false, the other probes won't happen due to C's
short-circuit rules.

> +	success &= piglit_probe_pixel_rgb(w - 1, 0, blue);
> +	success &= piglit_probe_pixel_rgb(0, h - 1, blue);
> +	success &= piglit_probe_pixel_rgb(w - 1, h - 1, blue);
> +
> +	return success ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> +
> +void piglit_init(int argc, char **argv)
> +{
> +	piglit_require_extension("GL_EXT_framebuffer_object");
> +	piglit_require_extension("GL_EXT_framebuffer_blit");
> +}
> 



More information about the Piglit mailing list