Interface graphiques sur Linux

by Laurent Cetinsoy published the 06/05/2024

computer graphique linux

Audience visée : Développeur (comme moi) qui n'a jamais bien trop compris comment marchait l'affichage graphique (comme moi).

C'est trop long, je lis pas

Aujourd'hui j'ai essayé de comprendre comment marche l'affichage graphique. Voilà mon cheminement d'apprentissage (et donc tout ne sera pas juste et il me reste des questions)

SDL (code source) : librairie multi OS d'affichage graphique. Elle utilise en arrière plan d'autre librairies. Par exemple sur Linux, elle peut utiliser 

X.org (code source): Gestionnaire de fenêtre (architecture client server) qui implémente ce qu'on appelle une API appelée  Direct Rendering Manager (mode-setting). Le client en C de X est la librairie Xlib (il existe aussi Xcb). Donc SDL quand il utilise le server X, utilise probablement xlib ? Si on veut on peut utiliser Xlib pour créer une fenêtre (penser à compiler avec l'option -Xl11) et se passer de SDL.

Il en existe d'autres implémentations de DRM comme Wayland ou libDRM (code source). Ce code montre comment utiliser libDRM et est bien commenté.

Mais que font libDRM ou X server ? Ils utilisent des appels System (du noyau linux) pour envoyer des instructions à la carte graphique via l'API Frame Buffer en utilisant la librairie qui est une API qui permet de faire abstraction du modèle de carte graphique (pas trop sur là). Pour envoyer les instructions à la Carte Graphique on utilise la librairie :

ioctl (doc) : qui sert à  communiquer avec les périphériques.

J'ai découvert ces trucs en lisant pas mal de code source, c'est intéressant !

Ressources et liens additionnels en bas de l'article

---

C'est trop intéressant, je lis  : 

Ne me demandez pas pourquoi je me suis perdu dans ce puits sans fond aujourd’hui, car je ne sais pas. En ce moment je refais du C pour Nowledgeable et je me suis demandé : Hmmhmm .. comment ça marche vraiment les interfaces graphiques ? Qui donne les ordres à la carte graphique et à l'écran au plus profond du système d'exploitation ? Attention : je ne suis pas expert, c'est mon cheminement d'apprentissage que je retranscris, et l'article pourra avoir des impécisions, ou pire, des erreurs (Oh mon dieu gardez moi de lire une telle chose - mais non calme toi, se tromper est une étape de l'apprentissage, même si en France on n'aime pas ça).

Imaginons que vous vouliez faire un programme avec une interface graphique. Et non, pas une application web, ou pire, une application Electron. Vous voulez faire une application Desktop ou un jeu vidéo comme avant en C (ou C++) ! Comment faire ? 

Eh bien il est possible d'utiliser la librairie SDL (ou Qt) qui est une librairie haut niveau pour créer et manipuler des fenêtres. SDL gère l'affichage à l'écran, les touches du claviers, etc. "Mais", me disais-je "elle ne communique sûrement pas directement avec l'écran ou la carte graphique, elle doit utiliser quelque chose d'autre !". Surtout qu'elle est cross plateforme : elle marche sur Linux, Windows et j'en passe. "Elle doit faire appel à des fonctions tierces différentes pour chaque OS pour créer les fenêtre et changer la couleur des pixels". Et en effet pour l'affichage, la SDL appelle des fonctions différentes si on est sur Windows (l'APIWin32 ou quelque chose comme ça ?) ou si on est sur Linux. Et du coup sur Linux, quelles sont ces fonctions ? 

Pour l'affichage graphique, beaucoup de distribution Linux utilisent X Server, un logiciel client-server. Elle dispose d'un client en C qui s’appelle Xlib. Donc si vous voulez dessiner une fenêtre en C vous pouvez utiliser Xlib sans utiliser SDL (compiler avec le flag -lX11). 

Mais tombant dans un schéma récursif infini digne des questions inlassablement posées par les enfants : comment marche X Server ? Est ce que c'est lui qui parle au GPU et tutti quanti ? Et si oui comment ? 

Le server X est en fait une implémentation de ce qu’on appelle l’API Direct Rendering Mode setting (DRM) qui va utiliser des appel système pour communiquer avec la carte graphique et lui donner des instructions. Les instructions sont envoyés avec la librairie ioctl qui permet de communiquer avec les périphériques de l'ordinateur.

Mais ces instructions qu'il faut envoyer à la carte, que sont-elles, d'où viennent-elles, qui les finance ? Changent-t-elles d'une carte à une autre ou d'un constructeur à l'autre ? Heureusement non, imaginez qu'il faille fucking écrire un code différent par carte graphique. Il existe une API qui s'appelle Frame Buffer (je commence à être moins sur) qui est un standard pour qui ne dépend pas de la CG. Le but d'un DRM et donc de créer des fonctions qui envoient les instructions pour manipuler l'API Frame Buffer avec ioctl. Là par contre je ne sais pas si ce standard est implémenté au niveau de l'hardware ou du driver ou c'est notre ami Linus qui normalise les appels pour chaque CG. Je suppose que c'est le driver qui fait ça. 

Bref, une implémentation DRM est simplement une librairie qui permet d'envoyer facilement les instructions pour gérer l'affichage sans avoir à se taper l'envoie du code d’exécution bas niveau. X n'est pas la seule, il en existe plusieurs ! Par exemple Wayland, petit frère de X qui devrait le remplacer progressivement (je n'ai pas trop suivi où en était cette histoire). Il existe aussi une implémentation qui s'appelle libDRM (source). Vous pouvez regarder les fichiers libDrm.c et libDRMMode.c

Voici un exemple pour afficher à l'écran avec libDrm (plutôt bien commenté). On voit néanmoins qu'il faut bien plus de code qu'avec Xlib ou SDL ! 

A l'issu de cette plongée en eaux profondes il me reste encore des questions : 

- Quel est le role d'OpenGL / OpenGL ES ? Quelles relations avec X ? 

- Idem pour Vulkain 

- Est ce que X utilise libDrm ou Xlib ou a sa propre implémentation en faisant les appels systems ? [2] suggère que X a sa propre implémentation ?

- Est ce que  ioctl est utilisé quand on code un driver? Ou est-ce que c'est utilisé pour communiquer avec le driver ? 

- Que se passe-t-il si j'envoie des instructions débiles à un de mes périphiques, genre le GPU avec ioctl ?

Ressources :

[1]man page de DRM 

[2]Lien entre X server et libDrm : question reddit

[3]https://jichu4n.com/posts/how-x-window-managers-work-and-how-to-write-one-part-i/

https://stackoverflow.com/questions/40543176/does-opengl-use-xlib-to-draw-windows-and-render-things-or-is-it-the-other-way-a