Manjaro 在笔记本上的多显示器配置

前言

很久之前,就给自己新买的笔记本装上了Manjaro。可惜由于笔记本是双显卡,总会有些奇奇怪怪的问题。
(参见下文题外话,关于Windows 10上双显卡的“优秀表现”
Manjaro上的问题就是,无法识别外置显示器,只能搁置。看着黑的发亮的显示器,真是十分让人恼火。
想用 Linux 怎么办? 只能装上 Ubuntu 了事。真香
Ubuntu 上不需要修改任何设置,直接就能识别外接显示器。
后来经过一阵探索,才在Manjaro上用上了外置显示器。终于摆脱了真香定律


背景

还是老规矩,我先介绍一下这个问题的背景。
解决方法请翻到解决方法一节。
环境:

  • intel 集成显卡+Nvidia 独立显卡
  • HDMI 与 Nvidia显卡相连接

症状:

  • 无法接外接显示器,接上后无论是系统设置还是inxi -Fx都无法识别外置显示器。
  • 检查启动日志,发现虽然开机时检测到了显示器,但后面就没有下文了。
  • 由于自带bumblebee驱动,故本人曾经尝试过用optirun在独显上运行glxgears,外置显示器会闪一下,然后No Signal Input.
    (这说明bumblebee是可以启动nvidia显卡的,但无法输出到外置显示器上)
  • 总之,外置显示器就像一面黑色的镜子,看着让人揪心QAQ。

失败方案

先说一下我的踩坑历程,有助于大家更好地解决这个问题。
即使沧海桑田(2333),失去了时效性,这篇文章也可以为大家提供解决相似问题的参考。
解决方法请翻到解决方法一节。

佛系配置

一般情况下,不做一番努力是无法取得成果的,不是么?

佛系配置,我说的意思是光靠系统驱动,不进行任何修改。
以下是我的失败历程。

  • video-linux是开源驱动,以前的Manjaro版本是可以通过开源驱动打开第二显示器的。
    (但是花屏,或只能显示鼠标指针)
    这个方案是我最早放弃的。
  • video-nvidia (non-free driver)
    带nvidia的驱动都是nvidia官方维护的闭源驱动,
    其中390xx是代表具有fermi技术的显卡(貌似是个老技术)
    本人的笔记本显卡是GTX10xx系列,故应该选择不带390xx的版本
    然而安装后,只能用外置显示器。

修改bumblebee配置

Manjaro默认安装的是bumblebee驱动。

维基这么说:Bumblebee - ArchWiki

Bumblebee is an effort to make NVIDIA Optimus enabled laptops work in GNU/Linux systems. Such feature involves two graphics cards with two different power consumption profiles plugged in a layered way sharing a single framebuffer.

bumblebee驱动是针对Nvidia Optimus的有益尝试,由bumblebee团队维护。
它可以实现像Windows下一样的体验,即一般的桌面体验用Intel集成显卡处理,
需要高性能的情况下调用NVIDIA显卡,以达到最大的节能效果。

可惜bumblebee并不能很好的支持双显示器。
我尝试过github repo上的解决方法,即修改bumblebee配置以支持双显示器。
不过最后失败了。
如果有兴趣的话,可以看:
Multi Monitor Setup

bumblebee & intel-virtual-output

这个我只成功过一次,不知道为什么无法复现了。
并且操作麻烦,不建议采用。
但是还是简述一下这个方案,提供参考。

Manjaro的开发者之一Jonathan在论坛里就说过这样一句话,

有的时候通过强制修改xorg.conf也能强制输出到第二显示器。

我后来还真的想出来了一个这样的方案。
首先,需有bumblebee。
参照了一个很老的设置双显示器的教程,那个时候还是开心农场Ubuntu 9.04横行的年代。
intel-virtual-output是bumblebee里面带的一个工具:

intel-virtual-output is a utility for Intel integrated graphics chipsets on hybrid systems. The tool connects local VirtualHeads to a remote output, allowing the primary display to extend onto the remote outputs.
简而言之,是创建一块大的虚拟显示器,然后把所有的显示器都拼接在一起。(是一次抽象,逻辑上连续,物理上分立)

我修改了一下原有方案,以便在bumblebee里面使用:
(当时的原有方案大概是2009年提出的,那个时候还没有bumblebee。)
打开/etc/bumblebee/xorg.conf.nvidia,按照自己的需求(分辨率,刷新率)修改如下配置:

/etc/bumblebee/xorg.conf.nvidia
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Section "Monitor"
Identifier "DVI"
Modeline "1680x1050_60.00" 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync
Option "PreferredMode" "1680x1050_60.00"
Option "LeftOf" "DP"
Option "DPMS" "true"
EndSection

Section "Monitor"
Identifier "DP"
Modeline "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
Option "PreferredMode" "1920x1080_60.00"
Option "RightOf" "DVI"
Option "DPMS" "true"
EndSection

Section "Screen"
Identifier "Screen0"
Device "Radeon" # e.g. Radeon, Intel, nvidia
Monitor "DP"
DefaultDepth 24
SubSection "Display"
Depth 24
Virtual 3600 2130 # 1920 + 1680 (3600), 1080 + 1050 (2130)
# 上面的Virtual 就是拼接出来的虚拟显示器的尺寸,可根据自己的需求修改
#
EndSubSection
EndSection

(以上内容摘自ArchWiki - Multihead
(原文我已经找不到了,上面的内容是等效的)
然后运行intel-virtual-output,外接显示器瞬间亮了。
不过我发现我的分辨率有问题,又改了一下配置,发现无法复现。
重启bumblebee服务,重启X服务器,重启电脑,重新编译内核都无效。
希望知道这个是怎么回事的朋友能告诉我一下。我觉得太玄学了。

分析问题

首先,在Ubuntu中,我并没有找到bumblebee,并且我选择的是NVIDIA驱动。
这意味着Ubuntu采用了另一套机制。
参照ArchWiki上面的说法),让Optimus显卡在linux里面有三种实现方法:

  1. BIOS里面禁用掉一个显卡。缺点也是显而易见的:难以切换显卡。
  2. 用nouveau的PRIME功能。但是性能没有专有驱动好,睡眠和挂起也会出现问题。
  3. 用Bumblebee。不过Bumblebee很难支持双显示器。
  4. 用专有驱动。
  5. 不知道是什么鬼的方法,叫nvidia-xrun,让X服务器跑在n卡上。(貌似和1一样,但是1是硬件层面上的禁用。)

解决方法

我找到了Manjaro论坛里面的一个帖子。(作者Jonathon,是Manjaro开发团队的)
刚开始没有成功,后来在朋友的提醒下,发现原来我缺了一些步骤!
我照着这个帖子的步骤原封不动地操作,成功了。所以,接下来一定要按照步骤严格操作才能成功~
以下内容均为本人的中文翻译。原帖在此 - How To Set up PRIME with NVIDIA proprietary driver

原帖前言

最新版的Xorg,内核,还有显卡驱动,都支持PRIME输出。不过设置有点麻烦。
下面我说一下如何在Optimus的笔记本上开启PRIME。

方法 优点 缺点
bumblebee 按需使用独立显卡,Manjaro默认配置 有一定的开销,对性能有所影响
PRIME 直接使用独立显卡,性能更强 两块显卡都一直供电,需要手动配置
optimus-manager 显卡切换更简单 暂不成熟,还在开发中

Note:最简单的方法就是在主板设置里面禁用集成显卡。如果你可以禁用的话,就直接禁用掉算了。
Note2: optimus-manager可以实现两块显卡的半自动切换。但是时至今日还在紧锣密鼓地开发中……
免责声明:NVIDIA Optimus在Linux下目前一团糟,硬件设置千差万别。所以这个教程可能有不适用之处,建议参考ArchWiki获取更多信息。
译者注: 其实直接禁用在现在的很多笔记本bios设置里都找不到的。
译者注2:反正我是按照这个步骤成功了。
译者注3:没让重启的时候千万不要重启。

第一步,移除Bumblebee

如果你选择了non-free驱动(其实是伪闭源驱动),mhwd将会自动安装bumblebee。
bumblebee很碍事,所以我们得先干掉它。

1
sudo mhwd -r pci nonfree 0300

第二步,安装NVIDIA驱动

(如果你的是fermi显卡,下列步骤的video-nvidia需要改为video-nvidia-390xx)
(一般来说不用改)

1
sudo mhwd -i pci video-nvidia

(之前此处typo,十分感谢评论区朋友的更正~)

第三步,修改MHWD设置

(如果你安装了NVIDIA驱动,而不是bumblebee驱动,)mhwd会自动生成设置,只让NVIDIA显卡工作。
我们必须得改一下这个配置,这样PRIME才能生效。

另起炉灶

首先要删掉/etc/X11/xorg.conf.d/90-mhwd.conf
(如果你不放心可以mv嘛~)
然后新建一个文件/etc/X11/xorg.conf.d/optimus.conf

/etc/X11/xorg.conf.d/optimus.conf
1
2
3
4
5
6
7
8
9
10
Section "Module"
Load "modesetting"
EndSection

Section "Device"
Identifier "nvidia"
Driver "nvidia"
BusID "PCI:1:0:0"
Option "AllowEmptyInitialConfiguration"
EndSection

注意:BusID一栏需要根据自己的电脑配置进行修改。
虽然大多数Optimus笔记本都是这个编号,但是我仍然建议你核对一下自己电脑的BusID的值。
BusID的值是这么查询的:lspci | grep -E "VGA|3D"
(更新:评论区就有位朋友是不一样的)
(我的电脑上确实是这个编号)

禁用模块

PRIME依赖于nvidia-drm,但mhwd在默认情况下会禁用它,我们需要手动启用。
此外,为了确保nvidia驱动正常开启,我们还需要禁用其他一些模块。
所以,我们需要对/etc/modprobe.d动动手脚。

首先,我们得把mhwd自动生成的黑名单删掉。
(译者注:不放心的话,就重命名,但是要把后缀名改掉,因为modprobe.d里面所有conf结尾的文件都会被执行)
比如这样:视情况而定,你的配置可能不同

1
2
3
ls /etc/modprobe.d/mhwd*
sudo rm /etc/modprobe.d/mhwd-gpu.conf
sudo rm /etc/modprobe.d/mhwd-nvidia.conf

然后我们要新建一个黑名单,屏蔽一些其他的模块。
新建一个文件,什么名字都可以,conf结尾就行
写入:

/etc/modprobe.d/nvidia.conf
1
2
3
blacklist nouveau
blacklist nvidiafb
blacklist rivafb

第四步,开启nvidia-drm.modeset

创建一个新文件,

/etc/modprobe.d/nvidia-drm.conf
1
options nvidia_drm modeset=1

第五步,设置启动脚本

我们要设置一下桌面环境的输出源。这是最难搞的部分,可能会花掉很长时间。
如果你现在重启,桌面环境的输出可能会有一些问题。
在笔记本上,就会是笔记本屏幕一片黑(但是如果有外置,外置会亮)

我们需要写一个启动脚本,让桌面环境加载的时候能够正确选择输出源。

注意,视你的具体环境(DM)执行下列的某一个步骤。

你并不需要做下列所有步骤

针对 LightDM (xfce默认)
创建一个文件,

/usr/local/bin/optimus.sh
1
2
3
4
#!/bin/sh

xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto

然后按照国际惯例(hhh),让它可写可执行:chmod a+rx /usr/local/bin/optimus.sh
现在你还得把它设置为启动脚本。
编辑/etc/lightdm/lightdm.conf,然后在[Seat:* ]这一节设置
display-setup-script=/usr/local/bin/optimus.sh

针对 GDM (Gnome默认)
创建一个文件

/usr/local/share/optimus.desktop
1
2
3
4
5
6
[Desktop Entry]
Type=Application
Name=Optimus
Exec=sh -c "xrandr --setprovideroutputsource modesetting NVIDIA-0; xrandr --auto"
NoDisplay=true
X-GNOME-Autostart-Phase=DisplayServer

(Exec处也可以替换成一个脚本,写一个就像LightDM里面一样的脚本)
然后建立连接,让它随着GDM启动。

1
2
sudo ln -s /usr/local/share/optimus.desktop /usr/share/gdm/greeter/autostart/optimus.desktop
sudo ln -s /usr/local/share/optimus.desktop /etc/xdg/autostart/optimus.desktop

针对 SDDM (KDE 默认)
创建一个文件:

/usr/share/sddm/scripts/Xsetup
1
2
3
4
 #!/bin/sh

xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto

然后用chmod让它变为可执行的文件。

第六步,最后的工作

译者注:如果以上的工作都已经完成,我建议你再做一步。
我当时没有做这一步,之后重启发现内核模块加载错误。
所以还是建议,编译一下内核。

1
sudo mkinitcpio -P linux

最后重启,大功告成。

验证是否成功

如果以上你都设置正确了,当你重启之后,可以敲glxinfo | grep -i vendor
然后看看是不是像下面这样的信息。

1
2
3
4
$ glxinfo | grep -i vendor
server glx vendor string: NVIDIA Corporation
client glx vendor string: NVIDIA Corporation
OpenGL vendor string: NVIDIA Corporation

如果是,说明你已经设置成功,可以欢呼了!
当然我有双显示器,一看显示器亮了就知道了2333

最后

题外话

虽然bumblebee存在诸多问题(比如双显示器问题),但是我真的要为开发人员点赞。
因为连Windows 10上的驱动,官方都做不好。
(据说在Windows 10 1803里面已经修复了,但1809里面又带回来了,服气。
而且nvidia和M$互相踢皮球。)

这个奇怪的问题(点击查看)当时也困扰了我很久
打开任务管理器没有任何占用,为啥还是一卡一卡的?
后来才知道,噢,原来是双显卡的坑。
听说最近19H1来了?反正我不想用Windows了。
自从Windows 7 之后我就没用过没bug的系统!

最后的最后

显卡真的是一个大坑啊。
我折腾这个驱动,前前后后断断续续差不多半年了(摊手)
这篇博客我写了两天才写完QAQ

希望我的这篇博文能帮到各位看官。 :)
新开的评论区(Gitment),有问题可以在下面留言哦~
(2019-8 更新:感谢评论区的小伙伴的支持哦)

参考资料

How To Set up PRIME with NVIDIA proprietary driver
Optimus - ArchWiki