多线程 X11 应用程序和 OpenGL
我正在尝试使用 libx11 创建一个多线程 opengl 应用程序 - 每个窗口一个单独的线程和一个管理器线程。
我在管理器线程中有一个事件循环:
while(true)
while(XQLength(mPlatformData->display)){
XNextEvent(mPlatformData->display, &event);
std::cout << "event" << std::endl;
}
}
对于单线程应用程序来说,这是一个很棒的事件循环,但是通过这种多线程设置,会发生奇怪的事情。
当我创建窗口时,我需要禁用事件队列,否则 GLXMakeCurrent 将挂起 - 我的整个线程都会停止,并且不执行任何操作。
我在网上找不到太多有关多线程 X11 应用程序的信息,我应该以不同的方式处理我的事件吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
众所周知,Xlib 有几个无法修复的运行时问题,这些问题在并发访问情况下表现出来。我猜你正在遇到其中之一。
这是创建 Xcb 的首要原因之一:修复 Xlib 的问题。 GLX 是针对 Xlib 指定的,因此对于 OpenGL 来说,这似乎是一个阻碍。然而,Xcb 周围有一个 Xlib,人们可以安全地使用它与 GLX 交互,并且仍然在程序的其余部分使用 Xcb: http://xcb.freedesktop.org/opengl/
我看到两种可能的解决方案:
在
XNextEvent
周围放置一个XLockDisplay
/Mutex GLX 调用每个;您不必锁定普通 OpenGL,只需锁定前缀为glX...
的函数即可。使用 Xcb 获得运行时正确的行为,并按照我上面链接的指南使其与 OpenGL/GLX 兼容。
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.
正如 eile 所说,您应该检查是否使用 XInitThreads。
当我使用后台线程绘制动画的窗口时,我能够从中得到一些好的结果。如果坚持绘制代码,似乎没有什么真正的问题。
如果您需要更多,并且因为您使用的是低级 libX11,最好的方法是打开多个 X11 连接并为每个顶级窗口使用一个连接。 10 年前,当我开发 BeOS 跨平台工具包时,我就这样做了,当时一切都比现在更糟糕。
您甚至可以将其用于事件处理和顶层的子窗口。但这需要一些非常棘手的 XEvent 掩码代码。
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.
你在渲染线程中做什么?无论如何,如果您在不同线程之间共享 Display* 连接,则必须调用 XInitThreads。
我在每个线程一个显示连接方面取得了很好的经验。使用 XSelectInput 获取主线程上的事件。窗口 ID 可在不同的 Display* 连接之间共享。
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.