OpenGL child windows (SketchUp)

Brian Bloniarz brian.bloniarz at gmail.com
Wed Feb 8 11:19:20 CST 2012


Hi all,

I could use a little help fixing a window lag and screen corruption
issue in SketchUp:
http://bugs.winehq.org/show_bug.cgi?id=25912
Long story short, I think the implementation of OpenGL child rendering
needs a small update.

As a reminder, this is how an OpenGL child window is setup:

static BOOL set_win_format( HWND hwnd, XID fbconfig_id ) {
    gl_drawable = XCreateWindow(...); // offscreen window
    XCompositeRedirectWindow(..., gl_drawable, CompositeRedirectManual);
}

Here XComposite extension is render into an offscreen window.
When it's time to display, the contents of that window are copied into
the visible onscreen parent window (physDev is the onscreen window,
gl_drawable is the offscreen window):

BOOL X11DRV_SwapBuffers(PHYSDEV dev)
{
    ...
    glXSwapBuffers(gdi_display, gl_drawable);

    ...
    /* The GL drawable may be lagged behind if we don't flush first, so
     * flush the display make sure we copy up-to-date data */
    XFlush(gdi_display);
    XCopyArea(gdi_display, gl_drawable, physDev...);
}

The XFlush() is the problem; the buffer swap must happen
before the copy, and accelerated renderers wouldn't guarantee to do
that on an X queue flush.

So how do you wait for a buffer swap? I wrote a test program,
can you say "undefined behavior"? I tested on a few drivers:

1) ATI fglrx binary driver:
glXSwapBuffers is instantaneous, existing code works fine.

2) NVidia binary driver:
glXSwapBuffers is asynchronous, neither XFlush() nor XSync()
is enough. Calling glXWaitGL or glFinish works.

3) Mesa DRI driver (Intel i915):
glXSwapBuffers is asynchronous. None of
XFlush/XSync/glXWaitX/glXWaitGL is enough. glFinish works.

4) r600g (Open Source accelerated ATI) driver:
glXSwapBuffers is asynchronous. None of the flush calls
wait for it (XFlush/XSync/glXWaitGL/glXWaitX/glFinish).

The last one is the tricky part -- this driver is also
based on the DRI, so I'm guessing it may appear on other
open-source accelerated drivers (looking at
http://www.x.org/releases/current/doc/dri2proto/dri2proto.txt
suggests that this is new behavior as of 1.99.2)

So how to come up with a common fix? I could think of 3
possibilities:

1) Use the GLX_OML_sync_control extension, it has an explicit
call to wait for a buffer swap. Not supported by NV or fglrx,
but we could fallback to glXWaitGL on those drivers. Probably
simplest.

2) Use the X Damage extension, wait for an XDamageNotify
event before copying. This should work everywhere, all
drivers probably implement damage so that compositing window
managers can use it.

3) Talk to the DRI people, maybe glXWaitGL should't return
when there's a pending a buffer swap. The GLX spec seems to
say it should wait, but it's a grey area and the Composite extension
was designed much later. Not a quick fix.

Any ideas or thoughts? If I hear nothing, I can code up a patch
that does (1), but it'd be great to hear from some people who
know this area well.

Thanks,
Brian Bloniarz



More information about the wine-devel mailing list