Il 08 febbraio 2012 18:19, Brian Bloniarz <brian.bloni...@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.