在多台显示器上使用 GLX RHEL -- OpenGL、XLib 和多台显示器(带线程)
Posted
技术标签:
【中文标题】在多台显示器上使用 GLX RHEL -- OpenGL、XLib 和多台显示器(带线程)【英文标题】:Using GLX on Multiple Monitors RHEL -- OpenGL, XLib, and Multiple Monitors (with threads) 【发布时间】:2012-02-27 21:01:31 【问题描述】:我面临的问题是我有一个基于 glx 的应用程序,它可以很好地在单个线程上呈现基本原语。我可以在两个屏幕之间移动 XWindow,并且我的渲染循环继续进行。但是,如果我的应用程序的任何部分都有线程,即使它没有进行任何 openGL 调用或触摸任何其他线程上的 XWindow,但当我将 XWindow 从一个屏幕移动到另一个屏幕时,我渲染的图形的主线程会丢失。
我做的第一个函数调用是 XInitThreads,所以我知道 X11 应该是线程安全的。正如我所说,这在一个线程上绘制基元时有效,但当我添加 1 个或多个线程时它不起作用。线程位于我无权访问源的库中。我只是被要求使用 X11 创建代码的窗口部分。
我应该寻找什么来解决这个问题?
另外请注意,我已经保证所有 glcalls 都发生在我从库中调用它们的线程上。
更新
[matt6809@hogganz400 SampleApp]$ cat /etc/X11/xorg.conf && echo "--------" && xrandr --verbose && echo "-------" && glxinfo && echo "-------" && xdpyinfo
# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings: version 295.20 (buildmeister@swio-display-x86-rhel47-05.nvidia.com) Mon Feb 6 22:13:16 PST 2012
# nvidia-xconfig: X configuration file generated by nvidia-xconfig
# nvidia-xconfig: version 295.20 (buildmeister@swio-display-x86-rhel47-05.nvidia.com) Mon Feb 6 22:13:40 PST 2012
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
Screen 1 "Screen1" RightOf "Screen0"
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
Option "Xinerama" "1"
EndSection
Section "Files"
FontPath "/usr/share/fonts/default/Type1"
EndSection
Section "InputDevice"
# generated from default
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/input/mice"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
# generated from data in "/etc/sysconfig/keyboard"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection
Section "Monitor"
Identifier "Monitor0"
VendorName "Unknown"
ModelName "DELL P190S"
HorizSync 30.0 - 81.0
VertRefresh 56.0 - 76.0
Option "DPMS"
EndSection
Section "Monitor"
Identifier "Monitor1"
VendorName "Unknown"
ModelName "DELL P190S"
HorizSync 30.0 - 81.0
VertRefresh 56.0 - 76.0
Option "DPMS"
EndSection
Section "Monitor"
Identifier "Monitor1"
VendorName "Unknown"
ModelName "DELL 1908FP"
HorizSync 31.0 - 83.0
VertRefresh 56.0 - 76.0
EndSection
Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "Quadro 4000"
BusID "PCI:15:0:0"
Screen 0
EndSection
Section "Device"
Identifier "Device1"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "Quadro 4000"
BusID "PCI:15:0:0"
Screen 1
EndSection
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
Option "TwinView" "0"
Option "TwinViewXineramaInfoOrder" "DFP-0"
Option "metamodes" "DFP-0: nvidia-auto-select +0+0"
SubSection "Display"
Depth 24
EndSubSection
EndSection
Section "Screen"
Identifier "Screen1"
Device "Device1"
Monitor "Monitor1"
DefaultDepth 24
Option "TwinView" "0"
Option "metamodes" "DFP-2: nvidia-auto-select +0+0"
SubSection "Display"
Depth 24
EndSubSection
EndSection
--------
Xlib: extension "RANDR" missing on display ":0.0".
RandR extension missing
[matt6809@hogganz400 SampleApp]$
【问题讨论】:
【参考方案1】:这只是一种预感,但可能是,OpenGL 上下文没有在线程之间干净地迁移。如果您完全控制 OpenGL 和窗口操作,您的问题并不清楚。
涉及 OpenGL 和多线程的常用方法是将所有 OpenGL 操作限制在一个特定线程中。
如果你不能确定这一点,你应该打电话
glXMakeContextCurrent(display, None, None, NULL); // GLX 1.3
或
glXMakeCurrent(display, None, NULL); // GLX 1.2 and earlier
在屈服于另一个线程之前完成 OpenGL 操作或完成 tasklet 以确保上下文与当前线程正确解除绑定。
在需要时相应地重新绑定上下文。
【讨论】:
我唯一可以简单地做到这一点的地方是在调用 swapbuffers 之后。我这样做无济于事。我确实可以控制设备的创建以及 glxMakeCurrent 和 glxSwapBuffers 函数。在我调用图书馆进行绘图之前,我会在绘图周围调用这些。此外,当调用 draw 时,我被承诺所有 gl 调用都是在您调用 draw 的线程上进行的。我的绘图调用在主线程上。 此外,当 XWindow 从一个屏幕拖到另一个屏幕时,所有 2 X (#CPUs) + 1 个线程都位于 pthread_cond_wait @MatthewHoggan:您的系统设置是什么(使用的 GPU、xorg.conf[.d] 输出的xrandr --verbose
、glxinfo
、xdpyinfo
)?
我运行了指定的命令并将它们作为更新发布。让我知道我是否可以为您提供任何其他帮助。
@MatthewHoggan:由于您将命令与&&
链接在一起,因此失败的 xrandr 会阻止进一步执行。请改用简单的;
。但我已经看到了一些东西:你已经启用了 Xinerama,这与 NVidia 的 TwinView 不兼容,后者带来了自己的 Xinerama 协议仿真。所以作为第一次测试,在服务器布局中切换Xinerama并再次测试。这也意味着只配置一个设备,现在配置两个,并使用 TwinView MetaModes。【参考方案2】:
我认为它必须是 GL 上下文。当您从一个屏幕移动到另一个屏幕时,您应该切换到具有该(新)显示的 GL 上下文。使用暴露事件来选择其他上下文。也就是说,创建两个上下文并使用 glxMakeCurrent(xdisplay,xwindow,xglcontext)。其中 xdisplay 是新的显示,而 xglcontext 将是另一个上下文)
【讨论】:
以上是关于在多台显示器上使用 GLX RHEL -- OpenGL、XLib 和多台显示器(带线程)的主要内容,如果未能解决你的问题,请参考以下文章
QXcbIntegration:无法创建平台 OpenGL 上下文,GLX 和 EGL 均未启用