piątek, 30 maja 2014

Multi Xorg Server, one input


    Sytuacja wygląda tak: mamy maszynę z Debian Wheezy a w niej dwie karty graficzne, każda z przynajmniej dwoma wyjściami na monitor. Nie ważne jakie modele. Ważne, że karty są dwóch różnych producentów i nie będą ze sobą współpracować - w moim konkretnym przypadku:



# lspci | grep -i vga
01:00.0 VGA compatible controller: Advanced Micro Devices [AMD] nee ATI Caicos [Radeon HD 6450]
03:00.0 VGA compatible controller: NVIDIA Corporation GF119 [GeForce GT 610] (rev a1)


   Konfiguracja obu tych kart na jednym X serwerze kończy się albo komunikatem "Segmentation fault", albo pustką na ekranie zamiast środowiska graficznego. Co nam pozostaje oprócz wymiany którejś z kart? Odpalenie kilku X serwerów w taki sposób, by każdy z nich korzystał tylko ze swojej karty graficznej, a całością dało się bez problemu posługiwać przy pomocy jednej myszki i klawiatury.

    Wbrew pozorom nie jest to jakieś strasznie trudne. Zakładam, że znamy jako tako składnię pliku /etc/X11/xorg.conf i umiemy przy jego pomocy skonfigurować sobie X-sy na zwykłej maszynie z jednym monitorem. Doświadczenie w konfiguracji z dwoma monitorami również może się przydać ;]

    Na początek warto przeczytać ten dokument. Oczywiście jest stary i nie aktualny, ale naprowadził mnie na właściwy trop ;) Najpierw konfigurujemy główną kartę graficzną (ang. primary display). W moim przypadku Radeon HD 6450 jest bez wątpienia mocniejszą kartą jak "low endowy" GeForce GT 610. Konfiguracja w pliku xorg.conf z użyciem RandR wygląda tak:

# cat /etc/X11/xorg.conf
Section "ServerLayout"
    Identifier  "display0"
    Screen      0  "Screen0" 0 0
    Option      "IsolateDevice"    "1:0:0"
EndSection

Section "Monitor"
    Identifier  "Monitor1"
    Option      "DPMS" "true"

    Option      "PreferredMode" "1920x1080"
    Option      "TargetRefresh" "60"
    Option      "Position" "0 0"
EndSection

Section "Monitor"
    Identifier  "Monitor2"
    Option      "RightOf" "Monitor1"
    Option      "DPMS" "true"

    Option      "PreferredMode" "1280x1024"
    Option      "TargetRefresh" "75"
    Option      "Position" "1920 0"
EndSection

Section "Device"
    Identifier  "Radeon HD 6450"
    Driver      "fglrx"
    BusID       "PCI:1:0:0"

    Option      "EnableRandR12" "true"
    Option      "Monitor-DFP2" "Monitor1"
    Option      "Monitor-CRT1" "Monitor2"
EndSection


Section "Screen"
    Identifier  "Screen0"
    Device      "Radeon HD 6450"
    DefaultDepth    24
    SubSection "Display"
        Viewport    0 0
        Virtual     3200 1080
        Depth       24
    EndSubSection
EndSection


    Jak widać, definiuje jeden wirtualny ekran złożony z dwóch monitorów. Jedyna magiczna opcja to "IsolateDevice", która stara się przypisać naszą konfiguracje tylko do urządzenia widocznego na szynie pci pod adresem 1:0:0, czyli karty Radeon. Pora na konfiguracje drugiego serwera X, którą umieścimy w pliku /etc/X11/xorg.conf.1 :

# cat /etc/X11/xorg.conf.1
Section "ServerLayout"
    Identifier  "display1"
    Screen      0  "Screen0" 0 0

    Option      "IsolateDevice"    "3:0:0"
    InputDevice "Generic Keyboard"  "CoreKeyboard"
    InputDevice "Configured Mouse"  "CorePointer"
    Option      "AutoAddDevices"    "false"
    Option      "AutoEnableDevices" "false"
EndSection

Section "InputDevice"
    Identifier  "Generic Keyboard"
    Driver      "void"
    Option      "CoreKeyboard"
EndSection

Section "InputDevice"
    Identifier  "Configured Mouse"
    Driver      "void"
    Option      "CorePointer"
EndSection

Section "Monitor"
    Identifier  "Monitor0"
    Option      "DPMS" "true"

    Option      "PreferredMode" "1280x1024"
    Option      "TargetRefresh" "75"
    Option      "Position" "0 0"
EndSection


Section "Device"
    Identifier  "GeForce GT 610"
    Driver      "nouveau"
#    Driver     "nvidia"
    BusID       "PCI:3:0:0"

    Option      "EnableRandR12" "true"
    Option      "Monitor-DFP0" "Monitor0"
EndSection

Section "Screen"
    Identifier  "Screen0"
    Device      "GeForce GT 610"
    DefaultDepth    24
    SubSection  "Display"
        Viewport    0 0
        Depth       24
    EndSubSection
EndSection


    Tutaj sprawa jest tylko odrobinę bardziej skomplikowana. Ponieważ nie chcemy by drugi X serwer przejmował wejście z klawiatury i myszki (inaczej pisalibyśmy na obu serwerach X jednocześnie), zdefiniowaliśmy te urządzenia podając jako sterownik "void" (wymagany pakiet xserver-xorg-input-void). Sterownik ten, to po prostu pusta wydmuszka która umożliwia uruchomienie X serwera bez klawiatury i myszki. Dodatkowo wyłączamy opcje "AutoAddDevices" oraz "AutoEnableDevices", inaczej myszka i klawiatura zostałyby i tak automatycznie wykryte - a tego przecież nie chcemy.

    W tym momencie możemy już wystartować środowisko graficzne. Ważne jest to, by oba serwery wystartowały na różnych wirtualnych konsolach (parametry vt8 i vt9) oraz by było pomiędzy nimi jak najmniej interakcji (parametry -novtswitch -sharevts). Zmienna DISPLAY również musi odpowiednio wskazywać na oznaczenie "ekranu" z którym odpalamy Xorg (parametry :0 i :1).

    Podstawowy X serwer możemy odpalić posługując się standardowym skryptem startowym (polecenie service), lub korzystając z takiego skryptu :

# cat display0.sh
#!/bin/bash

export DISPLAY=:0.0

/usr/bin/Xorg :0 -config /etc/X11/xorg.conf -audit 0 -br -verbose -novtswitch -nolisten tcp vt8 -isolateDevice PCI:1:0:0 &
sleep 10

sudo -u adrb /usr/bin/gnome-session &
sudo -u adrb /usr/bin/gnome-screensaver-command --lock


    Jak widać, korzystam z GNOME, ale z KDE również nie powinno być problemu. Uruchamiając GNOME przy pomocy gnome-session z poziomu mojego użytkownika (adrb) od razu się zalogujemy do środowiska, z tego powodu następne polecenie wymusza zablokowanie ekranu - chodzi o to byśmy musieli podać hasło. Drugą kartę uruchamiamy podobnym skryptem :

# cat display1.sh
#!/bin/bash

export DISPLAY=:1.0

/usr/bin/Xorg :1 -config /etc/X11/xorg.conf.1 -audit 0 -br -verbose -novtswitch -nolisten tcp vt9 -isolateDevice PCI:3:0:0 -sharevts &
sleep 10


sudo -u adrb /usr/bin/gnome-session &
sudo -u adrb /usr/bin/gnome-screensaver-command --lock


    Polecenia powyżej, wykonujemy oczywiście jako root. Na koniec zostało nam skonfigurować współdzielenie klawiatury i myszki. Można do tego celu próbować wykorzystać program x2x, ale moim zdaniem o wiele bardziej uniwersalny i bezbolesny jest Synergy, którego konfiguracja będzie wyglądać tak :

# cat /etc/synergy.conf
# synergy configuration file
#

section: screens
    display0:
    display1:
end

section: links
    display0:
        left = display1

    display1:
        right = display0
end


Możemy już startować serwer synergy :

$ synergys --daemon --config /etc/synergy.conf --name display0 -a 127.0.0.1

Oraz klienta, którego przypniemy do drugiego serwera X :

$ synergyc --name display1 --display :1 localhost

    Pozostaje życzyć udanej pracy na wielu monitorach na raz ;]