1

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.

  1. All the events such as ConfigureNotify, or Expose, are already compressed as is needed.
  2. The window background_pixmap is set as None.
  3. 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.

  1. The picture output of the back buffer after RedrawWindowFromBuffer() is what was expected.
  2. 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.
  3. 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.

null
  • 63
  • 6

1 Answers1

0

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).

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Background pixmap is already set to None so I think I might try setting the vertical retrace. Is there a way to check if it is currently being implemented or not? Some said it depends on the driver to decide. Some said to set opengl environment, and then, of course, there is glXSwapInterval. I once checked my NVDia setting to allow for vertical retrace but I am not certain if it truly functions or not since the window still continue to flicker. – null Aug 29 '13 at 16:54
  • @S.Aymerich: Truth to be told I think you're severely overcomplicating things. Keep it simple and straigt: Just call glXSwapBuffers once you're done drawing to a window. You should redraw anyway, don't worry about performance. – datenwolf Aug 29 '13 at 17:42
  • That is how it was done once, @datenwolf. The sad fact is that child windows' display when any re-size event is performed ( either on its siblings or its parent) suffer greatly. – null Aug 29 '13 at 23:43
  • If you have multiple subwindows instead of child windows I recommend using one single large OpenGL window, with glViewport + glScissor (and GL_SCISSOR_TEST enables) to partition it into a number of tiles. Much more hassle free. – datenwolf Aug 30 '13 at 01:32
  • Yes, those child windows are drawn too using opengl. While it could be much easier using glViewport to draw into different portions of one big window (which I believe that is what Blender did with theirs), the visual style selected for each child windows in mine, or their root, is not necessarily the same. Hence, the decision to implement the system as separate child windows. After a brief reading on swap_group, the extension could be what I need but if it is not widely supported, I am skeptical. – null Aug 30 '13 at 02:18
  • One of the reason, I signal my own batch of swap is that this needs to be portable to window as well. I don't quite understand 'the blocking before VSync is executed and buffer is truly swapped'. For then my implementation should not have worked at all. Still, it seems to work if the resize is performed on child windows now. It is the root window that gives me flicker. Perhaps I am missing something here? I'm sorry. I am slow but I really am trying to understand all these. – null Aug 30 '13 at 02:19
  • @S.Aymerich: The root window, or your top level window? That's a major difference. Regarding the difference in visual style: I don't see why you need separate child windows for that. – datenwolf Aug 30 '13 at 09:57
  • My mistake. It is the top level window to my applications. As for the difference in visual style, because some child windows have depth buffer, some don't; some are multisample; some aren't. ( Also, I have tried setting vSync to on. It flickers still. ) :{ – null Aug 30 '13 at 12:25
  • @S.Aymerich: How about you use a bunch of FBOs to which you render all the child window stuff and in a last step you composite that on the container window? Each FBO can have a completely different pixelformat configuration, and you'd not have to work with scissor testing, too. – datenwolf Aug 30 '13 at 12:49
  • It could be one of the solutions. It'd surely save me a lot of hassle of having to deal with all the re-sizing and exposing of events. (Though, considering FBO doesn't have an Accum buffer, I might still need to find an alternative to one.) Regretfully, It will require great scope of changes to the system, which I don't believe the time I have would suffice. (Would it be helpful to note that the window with children seems to flicker less in comparison with the window without one? It seems to be especially more so when there are more calculations involved in the actual redrawing process. ) – null Aug 30 '13 at 13:39
  • @S.Aymerich: Accum buffer? There are still people developing for that? I suggest using a texture array, which get's summed up in final composition step. Also there's no widespread HW accelerated support for accum buffer in most drivers. – datenwolf Aug 30 '13 at 14:04