X Window peut faire du multi-écran, voici comment (youhou mon premier howto réellement intéressant !). - étendu 25 janvier 2005

Oui, X Window peut faire du multi-écran, et oui X.org peut le faire. Mais c'est pas super documenté sur le net (ou je cherche comme un pied, ce qui est aussi une possibilité 😉).

Le pire, c'est que c'est pas très compliqué. Mais Xorg ne configure pas automatiquement la prise en charge multi-écrans, même s'il détecte plusieurs cartes ! Il détecte bien les cartes et moniteurs, mais en lançant un gestionnaire de fenêtres, on se retrouve avec un seul écran fonctionnel, alors que le test marche bien... Pire encore, si on a une carte multi-affichages, on n'a qu'une seule carte et un seul moniteur !

Lisez mon papier sur xorg.conf si ce n'est déjà fait, j'y explique les bases à connaître sur le fichier de configuration de X.org, et je vais me baser dessus pour l'étendre à la prise en charge multi-écrans.

Les prérequis pour une configuration multi-écrans, c'est déjà plusieurs écrans 🙂, et plusieurs cartes graphiques, ou un carte graphique pouvant gérer plusieurs écrans. De plus en plus de cartes ont cette fonction, il est probable que vous ayez une telle carte sans même le savoir. A fortiori si vous avez un ordinateur portable (assez) récent, la puce graphique intégrée en est capable.

Si vous n'avez pas tout ça, faut se faire une raison, il n'y aura pas de multi-affichage (je le précise, des fois on me pose des questions farfelues comme "peut-on lire une clé USB qui n'est pas reliée à l'ordinateur ?").

Si par bonheur (et abondance de place sur le bureau) vous avez deux écrans ou plus et des puces graphiques pouvant supporter vos écrans, on peut se tenter le coup de frime. 😉

Première étape, avoir une configuration Xorg qui marche, sur un écran (voir sinon). Si vous avez deux cartes vidéo, Xorg les aura trouvées (sinon voir plus bas pour une tentative de solution), et elles apparaîtront dans des sections Device séparées. Dans mon cas, j'ai une puce Intel Extreme Graphics 2 intégrée sur AGP et une Matrox Millenium PCI :

Section "Device"

        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz"
        ### [arg]: arg optional
        #Option     "NoAccel"            	# [<bool>]
        #Option     "SWcursor"           	# [<bool>]
        #Option     "ColorKey"           	# <i>
        #Option     "CacheLines"         	# <i>
        #Option     "Dac6Bit"            	# [<bool>]
        #Option     "DRI"                	# [<bool>]
        #Option     "NoDDC"              	# [<bool>]
        #Option     "ShowCache"          	# [<bool>]
        #Option     "XvMCSurfaces"       	# <i>
        #Option     "PageFlip"           	# [<bool>]
	Identifier  "Card0"
	Driver      "i810"
	VendorName  "Intel Corp."
	BoardName   "82865G Integrated Graphics Device"
	BusID       "PCI:0:2:0"
EndSection

Section "Device"

        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz"
        ### [arg]: arg optional
        #Option     "SWcursor"           	# [<bool>]
        #Option     "HWcursor"           	# [<bool>]
        #Option     "PciRetry"           	# [<bool>]
        #Option     "SyncOnGreen"        	# [<bool>]
        #Option     "NoAccel"            	# [<bool>]
        #Option     "ShowCache"          	# [<bool>]
        #Option     "Overlay"            	# [<str>]
        #Option     "MGASDRAM"           	# [<bool>]
        #Option     "ShadowFB"           	# [<bool>]
        #Option     "UseFBDev"           	# [<bool>]
        #Option     "ColorKey"           	# <i>
        #Option     "SetMclk"            	# <freq>
        #Option     "OverclockMem"       	# [<bool>]
        #Option     "VideoKey"           	# <i>
        #Option     "Rotate"             	# [<str>]
        #Option     "TexturedVideo"      	# [<bool>]
        #Option     "Crtc2Half"          	# [<bool>]
        #Option     "Crtc2Ram"           	# <i>
        #Option     "Int10"              	# [<bool>]
        #Option     "AGPMode"            	# <i>
        #Option     "AGPSize"            	# <i>
        #Option     "DigitalScreen1"     	# [<bool>]
        #Option     "DigitalScreen2"     	# [<bool>]
        #Option     "TV"                 	# [<bool>]
        #Option     "TVStandard"         	# [<str>]
        #Option     "CableType"          	# [<str>]
        #Option     "NoHal"              	# [<bool>]
        #Option     "SwappedHead"        	# [<bool>]
        #Option     "DRI"                	# [<bool>]
        #Option     "MergedFB"           	# [<bool>]
        #Option     "Monitor2HSync"      	# [<str>]
        #Option     "Monitor2VRefresh"   	# [<str>]
        #Option     "Monitor2Position"   	# [<str>]
        #Option     "MetaModes"          	# [<str>]
	Identifier  "Card1"
	Driver      "mga"
	VendorName  "Matrox Graphics, Inc."
	BoardName   "MGA 2064W [Millennium]"
	BusID       "PCI:1:7:0"
EndSection

Le pilote mga comporte beaucoup d'options, dont des références à un 2ème moniteur ("Monitor2Position"), mais la plupart sont destinées aux Milleniums récentes, dans la série G, pas mon ancêtre. 🙂

Les cartes sont correctement identifiées en tant que "Card0" et "Card1". On va pouvoir s'en servir directement.

Si vous avez une carte intégrée, c'est différent, vous n'avez qu'un seul Device, comme ceci :

Section "Device"
	Identifier  "Card0"
	Driver      "radeon"
	VendorName  "ATI"
	BoardName   "ATI Radeon Mobility M6"
	Option     "AGPMode" "4"
        #VideoRam   32768 
        # NOTE: Enabling VideoRam produces strange errors, 
        #       no problem, it detects 32MB anyway.
        BusID       "PCI:1:0:0"
EndSection

L'astuce, c'est qu'on sait que cette carte peut gérer deux moniteurs. On va donc la dupliquer :

Section "Device"
	Identifier  "Card0"
	Driver      "radeon"
	VendorName  "ATI"
	BoardName   "ATI Radeon Mobility M6"
	Option     "AGPMode" "4"
        #VideoRam   32768 
        # NOTE: Enabling VideoRam produces strange errors, 
        #       no problem, it detects 32MB anyway.
        BusID       "PCI:1:0:0"
EndSection

Section "Device"
	Identifier  "Card1"
	Driver      "radeon"
	VendorName  "ATI"
	BoardName   "ATI Radeon Mobility M6"
	Option     "AGPMode" "4"
        #VideoRam   32768 
        # NOTE: Enabling VideoRam produces strange errors, 
        #       no problem, it detects 32MB anyway.
        BusID       "PCI:1:0:0"
EndSection

On recopie tout pareil, sauf qu'on change le nom de la carte, en "Card1" sur la "deuxième" carte !

Notez que votre XFree86 ou X.org peut ne pas présenter tous ces paramètres. Par exemple, sous Ubuntu, et XFree86 4 (je connais pas la version exacte, désolé), on a ce genre de chose :

Section "Device"
	Identifier	"ATI Technologies, Inc. Radeon Mobility 9000 M9 (R250 Lf)"
	Driver		"ati"
	BusID		"PCI:1:0:0"
EndSection

Ils omettent les infos VendorName et BoardName, mais Identifier est très explicite. Ce qui n'est pas forcément pratique pour relire le fichier. Mais en même temps, Ubuntu n'est pas vraiment fait pour les geeks qui éditent les fichiers de conf X à la main. 🙂

Enfin, ajouter une option pour indiquer au driver de la carte quels affichages matériels dépendent de cette carte, avec la directive Screen (qui n'est pas la section Screen !) :

Section "Device"
	Identifier  "Card0"
	Driver      "radeon"
	VendorName  "ATI"
	BoardName   "ATI Radeon Mobility M6"
	Option     "AGPMode" "4"
        #VideoRam   32768 
        # NOTE: Enabling VideoRam produces strange errors, 
        #       no problem, it detects 32MB anyway.
        BusID       "PCI:1:0:0"
    Screen 0
EndSection

Section "Device"
	Identifier  "Card1"
	Driver      "radeon"
	VendorName  "ATI"
	BoardName   "ATI Radeon Mobility M6"
	Option     "AGPMode" "4"
        #VideoRam   32768 
        # NOTE: Enabling VideoRam produces strange errors, 
        #       no problem, it detects 32MB anyway.
        BusID       "PCI:1:0:0"
    Screen 1
EndSection

Voilà, on a maintenant deux cartes prêtes à l'emploi. 🙂 Si vous avez d'autres cartes ou si votre carte gère plus de deux affichages, continuez à copier-coller. 😉

J'ai également deux déclarations Monitor, et deux Screen, dans ce xorg.conf :

Section "Monitor"

	#DisplaySize	  300   230	# mm
 ### Uncomment if you don't want to default to DDC:
#	HorizSync    842150464.0 - 0.0
#	VertRefresh  809972032.0 - 0.0
	Identifier   "Monitor0"
	VendorName   "VSC"
	ModelName    "VE510s"
	Option	    "DPMS"
EndSection

Section "Monitor"

	#DisplaySize	  300   230	# mm
 ### Uncomment if you don't want to default to DDC:
#	HorizSync    1429222016.0 - 0.0
#	HorizSync    30.0 - 70.0
#	VertRefresh  1430467328.0 - 0.0
	Identifier   "Monitor1"
	VendorName   "DEL"
	ModelName    "DELL  E771p"
	Option	    "DPMS"
EndSection
Section "Screen"
	Identifier "Screen0"
	Device     "Card0"
	Monitor    "Monitor0"
	DefaultDepth	24
	SubSection "Display"
		Viewport   0 0
		Depth     1
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     4
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     8
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     15
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     16
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     24
	EndSubSection
EndSection

Section "Screen"
	Identifier "Screen1"
	Device     "Card1"
	Monitor    "Monitor1"
	DefaultDepth	24
	SubSection "Display"
		Viewport   0 0
		Depth     1
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     4
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     8
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     15
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     16
	EndSubSection
	SubSection "Display"
		Viewport   0 0
		Depth     24
	EndSubSection
EndSection

Le "Screen0" utilise la carte "Card0" et le moniteur "Monitor0", de même que "Screen1" utilise les "1". Si vous avez une carte multi-affichages, dupliquez les sections Monitor et Screen que vous avez, et éditez-les.

Pour Monitor, comme Xorg ne le détecte pas tout seul, il faut le fabriquer à la main. Mettez "Monitor1" comme Identifier, à peu près ce que vous voulez en VendorName et ModelName. Pour les taux de rafraîchissement, il faudra vous référer au manuel ou au site du constructeur, ou une autre ressource sur le net pour les trouver. Et faites attention à ne pas mettre n'importe quoi, sinon le moniteur risque de brûler...

Pour Screen, faites juste attention à associer les bonnes cartes et les bon écrans, et à le nommer correctement (si vous gardez cette nomenclature de "0", "1","2", etc, ça ne devrait pas être trop difficile 😉). Reportez-vous au manuel pour connaître les différents modes d'affichage (profondeur de couleur, résolution) pour les reporter dans les SubSecton "Display". Les profondeurs de couleurs devraient suffire, pour FreeBSD.

J'ai vu qu'il existait des variantes (toujours chez Ubuntu) :

Section "Monitor"
	Identifier	"Ecran générique"
	HorizSync	30-67
	VertRefresh	50-75
	Option		"DPMS"
EndSection

Section "Screen"
	Identifier	"Default Screen"
	Device		"ATI Technologies, Inc. Radeon Mobility 9000 M9 (R250 Lf)"
	Monitor		"Ecran générique"
	DefaultDepth	24
	SubSection "Display"
		Depth		1
		Modes		"1400x1050"
	EndSubSection
	SubSection "Display"
		Depth		4
		Modes		"1400x1050"
	EndSubSection
	SubSection "Display"
		Depth		8
		Modes		"1400x1050"
	EndSubSection
	SubSection "Display"
		Depth		15
		Modes		"1400x1050"
	EndSubSection
	SubSection "Display"
		Depth		16
		Modes		"1400x1050"
	EndSubSection
	SubSection "Display"
		Depth		24
		Modes		"1400x1050"
	EndSubSection
EndSection

La section Monitor a les fréquences de rafraîchissement de l'écran renseignés, alors que sur la même section de X.org de FreeBSD, elles sont auto-détectées par défaut. Donc dans le doute, suivez les préférences de votre serveur X, et pour ajouter une section, renseignez les valeurs qu'il mentionne dans les sections existantes (je sais pas si je suis clair, là 🙂.

De même, les sous-sections Display de la section Screen sont légèrement différentes. X.org de FreeBSD décrit une variable Viewport, alors que XFree86 de Ubuntu décrit une variable Modes. Je ne suis malheureusement pas expert en serveurs X pour dire si c'est une différence entre XFree86 et X.org ou si c'est une différence d'implémentation entre FreeBSD et Ubuntu... Donc c'est ce que je disais, renseignez les infos conformément à ce qui existe dans votre fichier quand vous spécifiez des écrans et cartes supplémentaires.

Enfin, passons au ServerLayout. Il y a juste deux options à vérifier. Mon xorg.conf par défaut me disait ça :

Section "ServerLayout"
	Identifier     "X.org Configured"
	Screen      0  "Screen0" 0 0
	Screen      1  "Screen1" RightOf "Screen0"
	InputDevice    "Mouse0" "CorePointer"
	InputDevice    "Keyboard0" "CoreKeyboard"
EndSection

Notez les paramètres de Screen 1. Il donne le nom de l'affichage à utiliser, et une position relative par rapport à l'écran principal, "Screen0". Par défaut, l'écran secondaire est sensé être placé à droite de l'écran principal, donc RightOf. Or mon écran secondaire est place à gauche du principal. Je vais donc remplacer cette option par LeftOf :

Section "ServerLayout"
	Identifier     "X.org Configured"
	Screen      0  "Screen0" 0 0
	Screen      1  "Screen1" LeftOf "Screen0"
	InputDevice    "Mouse0" "CorePointer"
	InputDevice    "Keyboard0" "CoreKeyboard"
EndSection

Le test (X -xfconfig /<emplacement>/xorg.conf) me donnera bien la bonne position d'écran, et si je déplace le curseur à gauche, il partira bien sur l'écran secondaire. Mais le bureau du gestionnaire de fenêtres sera toujours confiné à un seul écran !

Le truc, c'est une option jamais définie par défaut dans le xorg.conf : "Xinerama". Elle permet d'utiliser les différents écrans en bureau étendu :

Section "ServerLayout"
	Identifier     "X.org Configured"
	Screen      0  "Screen0" 0 0
	Screen      1  "Screen1" LeftOf "Screen0"
	InputDevice    "Mouse0" "CorePointer"
	InputDevice    "Keyboard0" "CoreKeyboard"
	Option		"Xinerama" "true"
EndSection

Et voilà, vous avez un affichage multi-écrans fonctionnel sous X ! 🙂

J'avais promis de dire un mot sur les cartes non reconnues, et je le fais ici. Il peut y avoir plusieurs raisons à la non-détection de la carte vidéo. Première raison, elle n'est pas supportée par la version de X que vous avez. Là, pas de miracles, il faut se récupérer le bon driver, le recompiler au besoin et retenter la détection. Si vous savez qu'elle est supportée et que pour une raison obscure elle n'est pas détectée, regardez dans le dmesg pour voir si elle apparaît dans les périphériques détectés par le noyau. Moi, la Matrox Millenium donne ça :

pci1: <display, VGA> at device 7.0 (no driver attached)

Le noyau sait que c'est une carte vidéo, mais n'a pas de pilote spécifique à y affecter. Notez que la carte est présente sur le bus pci1, périphérique 7.0. C'est ce nombre que vous devrez fournir à xorg.conf pour forcer l'utilisation de cette carte. Rappelez-vous ma section "Device" :

Section "Device"
	Identifier  "Card1"
	Driver      "mga"
	VendorName  "Matrox Graphics, Inc."
	BoardName   "MGA 2064W [Millennium]"
	BusID       "PCI:1:7:0"
EndSection

L'option BusID permet de désigner la carte utilisée. Il faut aussi déterminer le driver à utiliser pour la carte. Pour ça, je ne sais pas. 🙂 Mais en creusant sur le net, ça doit pouvoir se trouver...

Voilà, j'espère que ça a pu vous aider ! Merci de m'avoir lu. 🙂