Bug 35945

Summary: GLX contexts are not resized properly when using XCBOwnsEventQueue
Product: Mesa Reporter: Samuel Rødal <srodal>
Component: GLXAssignee: mesa-dev
Status: RESOLVED DUPLICATE QA Contact:
Severity: normal    
Priority: medium CC: ikrabbe.ask, psychon, srodal
Version: 7.10   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments: Example reproducing the bug
Samuel Rødal's code extended so that it prints events that are received (compile with -lX11 -lX11-xcb -lGL -lxcb)

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:
2.6.38-3-generic
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
#define XCB_DRI2_INVALIDATE_BUFFERS 1

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:

#ifdef XCB_USE_XLIB
    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);
        }
    }
#endif

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.