OpenGL child windows (SketchUp)

Roderick Colenbrander thunderbird2k at gmail.com
Wed Feb 8 14:33:34 CST 2012


On Wed, Feb 8, 2012 at 6:31 PM, Matteo Bruni <matteo.mystral at gmail.com> wrote:
> 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.
>
>

The offscreen X11 window code is a bit questionable and we knew that
when added it. I have to think a bit and need to look closely at the
GLX specs again. My gut feeling is that vsync related functions may
not work for our purpose since we are well in undocumented territory
by using offscreen Windows (pbuffers also don't have vsync defined).

glXWaitGL and friends were intended for syncing GLX and X, so this may
be the most reliable way. As you pointed out there may be bugs in DRI,
but this needs a careful read of the specs (will try to look at it).
As you said the damage extension can be used as well, but I think I
would lean to using the classic glX/X synchronization features first.

I hope to have some time tonight to look at this.

Roderick



More information about the wine-devel mailing list