问题
I'm trying to create a multithreaded opengl application with libx11 - with one separate thread per window, and one manager thread.
I have an event loop in the manager thread:
while(true)
while(XQLength(mPlatformData->display)){
XNextEvent(mPlatformData->display, &event);
std::cout << "event" << std::endl;
}
}
This is a great event loop for single threaded applications, but with this multithreaded setup strange things happen.
When I'm creating a window, I need to disable the event queue, or GLXMakeCurrent will just hang - my entire thread stops, and does nothing.
I can't find much information about multithreaded X11 applications on the net, should I handle my events differently?
回答1:
It is known that Xlib has several unfixable runtime issues that manifest in concurent access situations. I'm guessing you're running into exactly one of those.
This is one among the reasons why Xcb was created in the first place: Fix the problems of Xlib. GLX is specified against Xlib so this might seem like a show stopper when it comes to OpenGL. However there is a Xlib wrapping around Xcb and one can safely use that to interface with GLX and still use Xcb for the rest of the program: http://xcb.freedesktop.org/opengl/
I see two possible solutions:
Put a
XLockDisplay
/Mutex aroundXNextEvent
and the GLX calls each; you don't have to lock for ordinary OpenGL, just the functions prefixedglX...
.Use Xcb to get runtime correct behaviour and follow the guide I linked above to make it work with OpenGL/GLX.
回答2:
As eile said you should check that you use XInitThreads.
I was able to get some good results from it when i used a background thread to do the window drawings of an animation. There seems to be no real problem if you stick to drawing code.
If you need more then that and because you are using low level libX11 the best is just to open multiple X11 connections and use one connection per toplevel window. I did this 10 years ago when i played with developing a BeOS cross platform toolkit and when everything was in a worse state then it is now.
You can use this even for event handling and child windows of a toplevel. But this needs some very tricky code for the XEvent masks.
回答3:
What are you doing in your render threads? In any case, if you share a Display* connection across different threads you have to call XInitThreads.
I've made good experiences with one Display connection per thread. Use XSelectInput to get events on your main thread. Window IDs are shareable across different Display* connections.
来源:https://stackoverflow.com/questions/6402476/multithreaded-x11-application-and-opengl