[Xcb] Event processing and GLX

Dan Cecile dancecile at gmail.com
Mon Nov 21 05:11:10 PST 2011

(Sorry for the spam, hopefully this corrects the email formatting issues.)

On Sun, Nov 20, 2011 at 5:37 PM, Jamey Sharp <jamey at minilop.net> wrote:
> Hello, Dan!
> On Sun, Nov 20, 2011 at 01:06:12PM -0500, Dan Cecile wrote:
>> I'm starting to experiment with using XCB in a new OpenGL project, and
>> I'm running into a snag with resizing windows. After finding the
>> explanation that GLX requires Xlib data structures, I modeled some
>> code off of the wiki tutorial (http://xcb.freedesktop.org/opengl/).
>> Opening the window and drawing work properly. When the window size
>> increases, though, the GLX framebuffer stays at its original size, and
>> OpenGL cannot draw on the full size of the expanded window.
>> To simplify the problem, I've modified the "glxdemo" Mesa demo. The
>> original code, using pure Xlib, can be found in the Mesa Git
>> repository:
>>   http://cgit.freedesktop.org/mesa/demos/plain/src/xdemos/glxdemo.c
>> I've modified this code very slightly, replacing the Xlib event loop
>> with an event loop written in XCB. This is enough to trigger the
>> resizing problem (which does not exist in the original, pure Xlib
>> demo).
>> ...
>> The only other change I made was to give XCB ownership of the event
>> loop immediately after connecting to the X server:
>>    dpy = XOpenDisplay(NULL);
>>    XSetEventQueueOwner( dpy, XCBOwnsEventQueue );
> To debug this, I tried modifying the demo as you suggested, but also
> adding a default case to the switch statement over event types that
> prints the unhandled event type. Sure enough:
>        Resize event
>        Redraw event
>        unrecognized event 75
>        unrecognized event 74
>        unrecognized event 75
> On my server, xdpyinfo -queryExtensions says the DRI2 extension event
> base is 74, so event 74 is BufferSwapComplete and 75 is
> InvalidateBuffers.

My server has the same base of 74 for DRI2, and logging the unknown
events in the Mesa demo shows that 74 and 75 are also being delivered
on to my client.

> The DRI2 spec says InvalidateBuffers "is generated when the buffers the
> client had requested ... become inappropriate because they don't match
> the drawable dimensions anymore, or a buffer swap has been performed."
> The client is supposed to "bring them back up-to-date with another
> GetBuffers request."
> So the cause of your troubles is pretty clear: the client-side 3D
> driver needs to see those events, and it's expecting to get them from
> Xlib, but Xlib doesn't own the event queue so the events never arrive
> there.
> Much less clear is what to do about it. For now, I think your only
> option is to use Xlib for event handling, and just migrate all your
> request/response code to XCB. I'd love to hear any suggestions about how
> to do better, though.
> Jamey

I've changed my application to use Xlib for event handling, and now
resizing the OpenGL window is all working properly. As you've
suggested, I'll continue to use XCB for my other X server messaging.

I dug a little bit into how Xlib is forwarding these events to the GLX
DRI2 engine. Here is the detailed flow:

  1. The event ID, DRI2_InvalidateBuffers, is defined in the prototype

  2. Mesa handles this event inside its DRI2WireToEvent function.
     (Mesa, src/glx/dri2.c)

  3. That event handler gets registered by a libxext macro,

  4. The macro calls into libxext's XextAddDisplay function.
     (libext, src/extutil.c)

  5. Finally, we've made it to Xlib, where libxext is calling
     XESetWireToEvent. That Xlib function sets up a callback entry in
     the Display structure's "event handling vector" (event_vec).
     (Xlib, src/InitExt.c)

  6. The only place the "wire" callback is called, is from _XEnq.
     (Xlib, src/XlibInt.c)

  7. Events are enqueued from XCB (inside Xlib) to the _XEnq function
     via the handle_response function.
     (Xlib, src/xcb_io.c)

One insight here is that any other Xlib extensions that use
XEXT_GENERATE_FIND_DISPLAY or XextAddDisplay will have the exact same

A simple solution, short of converting these extension libraries to
XCB, would be to add a new function to Xlib-xcb.h that would run the
"wire-to-event" handlers from the Display structure's "event_vec"
field. The new function would take an xcb_generic_event_t pointer, and
run any applicable handlers.

Dan Cecile

More information about the Xcb mailing list