On 10/29/2013 01:19 PM, Federico Mena Quintero wrote: > From: Federico Mena Quintero <feder...@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 <hverb...@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"); > +} > _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit