[Xcb] Event processing and GLX

Dan Cecile dancecile at gmail.com
Mon Nov 21 05:08:15 PST 2011

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:>>>>
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
unknownevents in the Mesa demo shows that 74 and 75 are also being
deliveredon 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
nowresizing the OpenGL window is all working properly. As
you'vesuggested, I'll continue to use XCB for my other X server
I dug a little bit into how Xlib is forwarding these events to the
GLXDRI2 engine. Here is the detailed flow:
  1. The event ID, DRI2_InvalidateBuffers, is defined in the prototype
    header.     (/usr/include/X11/extensions/dri2proto.h)
  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
useXEXT_GENERATE_FIND_DISPLAY or XextAddDisplay will have the exact
A simple solution, short of converting these extension libraries
toXCB, 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.
Cheers,Dan Cecile

More information about the Xcb mailing list