C++ 多线程环境中的XSetWMProtocols和glXCreateContext调用顺序
编辑:我在下面发布了一个很好的解决方案,解决了整个渲染器分离问题 我最近正在多线程X11环境中使用OpenGL。 我发现以下内容编译、链接和运行良好 但是,在尝试根据自己的需要修改代码之后,我遇到了一个奇怪的问题 在本教程中,XCreateWindow、glXCreateContext、XSelectInput和XSetWMProtocols的调用顺序如下:C++ 多线程环境中的XSetWMProtocols和glXCreateContext调用顺序,c++,multithreading,x11,glx,C++,Multithreading,X11,Glx,编辑:我在下面发布了一个很好的解决方案,解决了整个渲染器分离问题 我最近正在多线程X11环境中使用OpenGL。 我发现以下内容编译、链接和运行良好 但是,在尝试根据自己的需要修改代码之后,我遇到了一个奇怪的问题 在本教程中,XCreateWindow、glXCreateContext、XSelectInput和XSetWMProtocols的调用顺序如下: param[i].win = XCreateWindow(param[i].d_, root, 200,200,
param[i].win = XCreateWindow(param[i].d_, root, 200,200,
300,200, 0, visInfo->depth, InputOutput, visInfo->visual,
CWColormap,
&windowAttr);
param[i].ctx = glXCreateContext(param[i].d_, visInfo, NULL, True);
XSelectInput(d, param[i].win, StructureNotifyMask);
XSetWMProtocols(d, param[i].win, &(delMsg), 1);
请注意,XCreateWindow和XSelectInput/XSetWMProtocols使用不同的显示连接
但是,将调用顺序更改为
param[i].win = XCreateWindow(param[i].d_, root, 200,200,
300,200, 0, visInfo->depth, InputOutput, visInfo->visual,
CWColormap,
&windowAttr);
XSelectInput(d, param[i].win, StructureNotifyMask);
XSetWMProtocols(d, param[i].win, &(delMsg), 1);
param[i].ctx = glXCreateContext(param[i].d_, visInfo, NULL, True);
程序失败了
失败请求的X错误:BadWindow(无效窗口参数)失败请求的主要操作码:2(X_ChangeWindowAttributes)
失败请求中的资源id:0x5000002失败请求的序列号 请求:17输出流中的当前序列号:18 这似乎是由XSetWMProtocols引起的 由于使用了不同的显示连接,如果一开始整个事情都不起作用,我不会感到惊讶。但不知何故,在调用glXCreateContext之后,一切似乎都奇迹般地好了 我对X11/GLX编程比较陌生,我错过了什么吗?glXCreateContext执行什么样的魔术?还是发生了什么事? 或者我应该继续,因为OpenGL和多线程似乎总是会引起问题 我的解决方案: 我很懒,只是使用教程中的方法。这一直有效,直到我的项目中添加了freetype,这突然又给了我一个糟糕的窗口崩溃。因此,即使一切看起来都很好,当您从不同的线程工作时,X11在您不在的时候严重地占用了一些内存。(不是我,我和瓦尔格林核实过) 我当前的解决方案正如n.m.评论的那样:我将所有内容都放在一个GUI线程(X11和GL/GLX调用)中,其他线程永远无法使用该线程的资源。但是,必须记住两件事,因为这可能会减慢渲染循环:
- 缓慢的消息处理延迟渲染(如下所述)
- 缓慢的渲染延迟了消息处理(我的问题)
:我同意n.m.的观点,我是编写教程的人D 我试图解决的问题是将事件循环与渲染循环解耦,这样我可以在不影响渲染的情况下重播到事件,反之亦然。我正在编写一个LUA框架,我的“processMessage(event)”函数可能会调用用户定义的LUA函数 在我编写事件循环的过程中,我遇到了很多问题,就像你遇到的问题一样,我也尝试了在Fedora上工作但在Ubuntu上崩溃的XCB,在经历了很多头痛之后,我发现了一个解决方案,它有不同的显示(因为X服务器就像服务不同的进程),有共享的GlContext和另一个加载线程(纹理和网格) 回到你的问题:
XSetWMProtocols(...)
希望在创建windows的位置显示相同的内容,但只在某些版本的X上显示。这就是为什么我现在使用Qt。我在跨平台项目中基本上经历了多线程X11和Win32的相同尝试 我注意到的一点是,X11并没有像上面的帖子所指出的那样修改内存。当然,各种命令的顺序有些奇怪,但一旦你做对了,它看起来相当稳定 特别是有一件事差点让我认输,那就是背景GPU处理!正是这种非常奇怪且难以捕捉的运行时竞争状况让我认为操作系统是罪魁祸首 在将纹理发送到显示列表中的卡片之后(在实现freetype时也是如此),立即绘制资源有时会导致字体显示列表的轻微损坏,即使对于以后的绘制也是如此。显示列表本身已经损坏,我甚至求助于实现一个全局OpenGL锁来证明线程不是罪魁祸首。但它为什么会被破坏?操作系统?不,是GPU 我相信共享的GLX环境会在某些卡上强制执行不同的行为,特别是在我的系统上的nvidia。不是其他线程造成了我的麻烦,而是createContext调用上的shared标志加上在使用资源之前缺少glFinish()。还有一些最佳实践,我将在下面解释 在99%的运行中,即使使用多线程,如果没有glFinish()也可以正常工作。只有在加载时才会出现这种情况,因此不断停止/重新启动应用程序最终会暴露它。如果它加载的所有内容都没有问题,那么从那时起应用程序就会运行良好。如果出现问题,图像将一直损坏,直到我重新加载它 所有的问题都是通过遵守这些简单的规则来解决的