OpenGL child windows (SketchUp)

Matteo Bruni matteo.mystral at gmail.com
Wed Feb 8 12:31:38 CST 2012


Il 08 febbraio 2012 18:19, Brian Bloniarz <brian.bloniarz at gmail.com> ha scritto:
> 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
>
>

Nice analysis.
I'm not really such an expert in the area, but I think both (1) and
(2) make sense. I'm not sure in (1) case about the glXWaitGL call, as
technically glXSwapBuffers is not a GL call, but given that it works
for you (while XSync doesn't) on Nvidia, I guess it's fine... Make
sure it works correctly on all the drivers you mentioned, or even that
e.g. it doesn't cause excessive slowdowns.



More information about the wine-devel mailing list