My situation is like this. I wrote a code that checked a group of windows if their content are eligible to be swapped or not (that is all the redrawing are successfully performed on the said window and all its children after a re-sizing event). Should the conditions be met, I performed glXSwapBuffers call for the said window, and all its children. My aim was to allow for a flicker-freed-upon-resizing system. The child windows were arranged in tile fashion, and does not overlap. Between them, the function appeared to work. My issue however, arise with the parent. Sometime during the re-sizing, its content flickers. So far, this is what I have implemented.
- All the events such as ConfigureNotify, or Expose, are already compressed as is needed.
- The window background_pixmap is set as None.
- Understanding that whenever an Expose event is generated, window background content is lost. With every redrawing done, I keep always keep the copy of the finished redraw in my own allocated buffer. (Neither a pixmap or fbo, but it suffices for now.)
My logic for each call to glXSwapBuffers() is this.
void window_swap( Window *win ) {
Window *child;
if ( win ) {
for ( child=win->child; child; child=child->next )
window_swap( child );
if ( isValidForSwap( win ) ) {
glXMakeCurrent( dpy, win->drawable, win->ctx );
glDrawBuffer( GL_BACK );
RedrawWindowFromBuffer( win, win->backing_store );
glXSwapBuffers( dpy, win->drawable );
}
}
}
Which...should serve, the content is always restored before a call to swap. Sadly, it did not appear so in the implementation. From the above code, I make some adjustment for the purpose of debugging by outputting what should be in the buffer as following.
void window_swap( Window *win ) {
if ( win ) {
if ( isValidForSwap( win ) ) {
glXMakeCurrent( dpy, win->drawable, win->ctx );
glDrawBuffer( GL_BACK );
OutputWindowBuffer( "back.jpg", GL_BACK );
RedrawWindowFromBuffer( win, win->backing_store );
glXSwapBuffers( dpy, win->drawable );
glDrawBuffer( GL_BACK );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
OutputWindowBuffer( "front_after.jpg", GL_FRONT );
OutputWindowBuffer( "back_after.jpg", GL_BACK );
}
}
}
The function OutputWindowBuffer() use standard glReadPixel() to read the buffer content and then output it as image. Which buffer is to be read is determined by the parameter passed into the function. What I've found out with the output picture is this.
- The picture output of the back buffer after RedrawWindowFromBuffer() is what was expected.
- The picture output of the back buffer after the swap is filled with the cleared colour as was expected. Thus, it is not the case that glReadPixel might be lagging in its execution when it was called for the Front buffer as some discovered bug about intel system seemed to suggest once.
- The picture output of the front buffer after the swap show mostly black artifacts (My window's colour is always cleared to other colour before each drawings).
Is there other plausible explanations as to why swapping the buffer, does not appear to swap the buffer? Is there other routes I should be looking into as to implement a flicker-free re-sizing? I have read an article suggesting the use of WinGravity, but I'm afraid I don't quite comprehend it yet.
If your windows have a background pixmap set, then at every resizing step they get filled with that, before the actual OpenGL redraw commences. This is one source of flicker. The other problem is glXSwapBuffers not being synched to the vertical retrace. You can set this using glXSwapInterval.
So the two things to do for flicker free resizing: Set a nil background pixmap and enable glXSwapBuffers synched to vertical retrace (swap interval 1).