Bug 35945 - GLX contexts are not resized properly when using XCBOwnsEventQueue
Summary: GLX contexts are not resized properly when using XCBOwnsEventQueue
Status: RESOLVED DUPLICATE of bug 42131
Alias: None
Product: Mesa
Classification: Unclassified
Component: GLX (show other bugs)
Version: 7.10
Hardware: x86-64 (AMD64) Linux (All)
: medium normal
Assignee: mesa-dev
QA Contact:
Depends on:
Reported: 2011-04-04 03:17 UTC by Samuel Rødal
Modified: 2012-01-06 00:01 UTC (History)
3 users (show)

See Also:
i915 platform:
i915 features:

Example reproducing the bug (1.45 KB, application/gzip)
2011-04-04 03:17 UTC, Samuel Rødal
Samuel Rødal's code extended so that it prints events that are received (compile with -lX11 -lX11-xcb -lGL -lxcb) (3.13 KB, application/octet-stream)
2012-01-03 04:09 UTC, Uli Schlachter

Description Samuel Rødal 2011-04-04 03:17:21 UTC
Created attachment 45213 [details]
Example reproducing the bug

When resizing an X window, the GLX context isn't resized. This bug appears when using XSetEventQueueOwner(dpy, XCBOwnsEventQueue) and using xcb to read events (xcb_poll_for_event or xcb_wait_for_event), but not when using XNextEvent to read events.

Comment out #define USE_XCB in the supplied example and the GLX context is resized as expected.

System information:
Ubuntu 10.10
Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
OpenGL version string: 2.1 Mesa 7.11-devel
Comment 1 Uli Schlachter 2012-01-03 04:09:53 UTC
Created attachment 55077 [details]
Samuel Rødal's code extended so that it prints events that are received (compile with -lX11 -lX11-xcb -lGL -lxcb)

I added a little printf to see what events are received (and piped the output through sort -u to make it less annoying).

The USE_XCB-version sees an event with type 75 which the Xlib version doesn't see. Event 75 is DRI2's event base +1 here:

$ xdpyinfo -queryExtensions | grep DRI2
    DRI2  (opcode: 137, base event: 74)

According to xcb's dri2.h, this is a DRI2_InvalidateBuffers event:

$ grep ' 1' projects/libxcb/src/dri2.h | tail -n1

So the question is: What happens to that event when using Xlib?
Mesa's src/glx/dri2.c, function DRI2WireToEvent() knows the answer. Mesa does some internal processing for the event (function dri2InvalidateBuffers()) and then returns "False" which means Xlib can't process the event and thus doesn't return it to the application.

So the problem is that in the USE_XCB version dri2InvalidateBuffers() isn't called.
To fix this, a new function has to be added to mesa which the application has to call for DRI2_InvalidateBuffers events (with XCB there is no way for mesa to hook into the event processing and get a callback from xcb). Or does anyone see an alternative solution?
Comment 2 ikrabbe.ask 2012-01-05 03:17:58 UTC
This is the same behaviour as reported in the bug below.
I attached some test files to #42131 to work around that resize bug, that might even show a more efficient method but resizing all those windows. It's based upon creating a glX Overlay Window (glXCreateWindow or the xcb equivalent) and keep the size of that overlay constant (at screen size) just changing the glViewport, to match the window size.

That might have the good effect that the buffers never need to be invalidated, but simply stay constant size. Depending on the usage of the window, you can define a maximum size that is allocated and never has to be exceeded later.

Of course the bug still remains and should be fixed someday...

*** This bug has been marked as a duplicate of bug 42131 ***
Comment 3 ikrabbe.ask 2012-01-05 03:19:10 UTC
Sorry, but the other bug should be duplicate of this bug... I haven't seen the quite old date of this number.
Comment 4 Samuel Rødal 2012-01-06 00:01:22 UTC
For the record, here's what the current work-around in Qt looks like:

    if (!handled) {
        // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any.
        // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events.
        Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent((Display*)m_xlib_display, response_type, 0);
        if (proc) {
            XESetWireToEvent((Display*)m_xlib_display, response_type, proc);
            XEvent dummy;
            event->sequence = LastKnownRequestProcessed(m_xlib_display);
            proc((Display*)m_xlib_display, &dummy, (xEvent*)event);

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.