我正在尝试使用libx11创建一个多线程opengl应用程序 - 每个窗口有一个单独的线程,还有一个管理器线程。
我在经理线程中有一个事件循环:
while(true)
while(XQLength(mPlatformData->display)){
XNextEvent(mPlatformData->display, &event);
std::cout << "event" << std::endl;
}
}
对于单线程应用程序来说,这是一个很棒的事件循环,但是这个多线程设置会发生奇怪的事情。
当我创建一个窗口时,我需要禁用事件队列,否则GLXMakeCurrent将挂起 - 我的整个线程停止,并且什么都不做。
我不能在网上找到有关多线程X11应用程序的更多信息,我应该以不同的方式处理我的事件吗?
答案 0 :(得分:2)
众所周知,Xlib有几个不可修复的运行时问题,这些问题在concurent访问情况中表现出来。我猜你正在遇到其中一个。
这是Xcb首先创建的原因之一:解决Xlib的问题。 GLX是针对Xlib指定的,因此在OpenGL方面,这似乎是一个显示停止。然而,在Xcb周围有一个Xlib包装,可以安全地使用它来与GLX连接,并且仍然将Xcb用于程序的其余部分:http://xcb.freedesktop.org/opengl/
我看到两种可能的解决方案:
将XLockDisplay
/ Mutex放在XNextEvent
左右,GLX各自调用;你不必为普通的OpenGL锁定,只需要以glX...
为前缀的函数。
使用Xcb获取运行时正确的行为,并按照上面链接的指南使其与OpenGL / GLX一起使用。
答案 1 :(得分:2)
正如eile所说,你应该检查你是否使用了XInitThreads。
当我使用后台线程来制作动画的窗口图时,我能够从中获得一些好的结果。如果你坚持使用绘图代码,似乎没有真正的问题。
如果您需要更多,那么因为您使用的是低级别的libX11,最好只是打开多个X11连接并在每个顶层窗口中使用一个连接。 10年前,我在开发BeOS跨平台工具包的时候做了这个,当一切都处于更糟的状态时,现在就是这样。
您甚至可以将此用于事件处理和顶级子窗口。但这需要一些非常棘手的XEvent掩码代码。
答案 2 :(得分:1)
你在渲染线程中做了什么?在任何情况下,如果您在不同的线程之间共享Display *连接,则必须调用XInitThreads。
我为每个线程的一个Display连接做了很好的体验。使用XSelectInput获取主线程上的事件。窗口ID可以跨不同的Display *连接共享。