Plan directeur 14 phases / 5 ans (REDOX_COSMIC_XWAYLAND_RS_PLAN.md).
Phase 1 — Audit Redox (docs/existing-redox-gui.md, 486 lignes) :
- Orbital, graphics-ipc (API DRM compatible Linux subset KMS), inputd, vesad
- relibc support : AF_UNIX, SCM_RIGHTS, shm_open, mmap, poll
- 3 manques identifiés : memfd_create, keymap XKB, AT-SPI
Phase 2 — Validation primitives sur Redox via redoxer (5 tests + 1 POC) :
- test-unix-socket : SOCK_STREAM Wayland-shaped roundtrip
- test-fd-passing : SCM_RIGHTS mono-process (artefact kernel)
- test-fd-passing-fork : SCM_RIGHTS multi-process (validation Wayland critique)
- test-shm-open : shm_open + mmap + persistance + unlink
- test-poll-multifd : poll() multiplexing + POLLHUP
- poc-pixels : datapath shm + SCM_RIGHTS bout en bout (10000 pixels ARGB)
Phase 3 — wayland-rs sur Redox (compile + runtime) :
- wayland-{scanner,backend,server,client} compilent pour x86_64-unknown-redox
sans patch upstream (rustix supporte Redox via libc backend)
- test-handshake : server/client wl_registry handshake roundtrip
- test-shm-pipeline : pipeline complet (ListeningSocket Unix réel + fd passing
via wl_shm.create_pool + wl_shm_pool + wl_buffer + wl_surface + commit +
serveur lit pixels via fd reçu, validation pixel-perfect)
Verdict phase 3 : wayland-rs upstream est viable sur Redox out-of-the-box,
le port "Wayland sur Redox" est désormais un problème de compositor à écrire,
pas de stack à porter.
Prérequis build : redoxer (pas cargo direct, car CMSG_NXTHDR/CMSG_DATA
ne sont pas linkés autrement vers librelibc.a).
Leyoda 2026 – GPLv3
19 KiB
Audit Phase 1 — Existant Redox GUI
Document produit le 2026-05-08 dans le cadre du plan directeur
REDOX_COSMIC_XWAYLAND_RS_PLAN.md(phase 1 : audit avant code).Périmètre : comprendre l'architecture graphique actuelle de Redox (Orbital + drivers + primitives) pour calibrer le portage Wayland.
Résumé exécutif
Redox dispose déjà d'une fondation graphique plus mûre que prévu :
- Une API DRM compatible Linux (subset KMS) exposée via
graphics-ipcet utilisée par Orbital - Plusieurs drivers : VESA firmware (
vesad), virtio-gpu (virtio-gpud), Intel HD (ihdgd) - Un input multiplexer (
inputd) qui gère VT switching, keymaps, producteurs/consommateurs - Orbital très compact (~3900 lignes Rust) qui valide le pattern serveur-clients via scheme
Côté primitives système, l'essentiel de ce que Wayland exige est déjà là :
- AF_UNIX sockets via le scheme
chan:✅ sendmsg/recvmsgavec SCM_RIGHTS implémenté (fd passing) ✅shm_openvia/scheme/shm/✅mmap MAP_SHARED✅poll/epoll✅- ⚠️
memfd_create: numéro syscall défini mais implémentation à vérifier
Conclusion : la phase 2 (primitives OS) du plan directeur sera moins lourde que craint. La majorité des briques existent — il faudra surtout valider le comportement par tests dédiés.
1. Architecture Orbital
1.1 Point d'entrée et boot
orbital/src/main.rs (82 lignes) :
main()
└─ orbital()
├─ lit env "VT" (passé par inputd au boot)
├─ Orbital::open_display() ← ouvre display via inputd
├─ exec "inputd -A <vt>" ← s'enregistre comme handler du VT
├─ Config::from_path("/ui/orbital.toml")
├─ OrbitalScheme::new(displays, config)
└─ orbital.run(scheme, login_cmd) ← event loop principal
Note séquence de boot : c'est inputd qui orchestre l'ouverture du display
au moment où le VT s'active. Orbital ne touche pas directement aux drivers
graphiques — il passe par inputd qui lui retourne un fd /scheme/.../v2/....
1.2 Event loop (core/mod.rs, 662 lignes)
Architecture deux-fd :
EventQueue<Source>
├─ Scheme fd (clients Orbital) → SchemeSync trait
└─ Input fd (depuis inputd consumer) → ConsumerHandleEvent::Events
Patterns clés :
- Utilise
event::EventQueue(crateredox_event) — équivalent Redox dewl_event_loopWayland ouepollLinux - Chaque source a son fd, multiplexé en édge-triggered READ
- Les requests scheme bloquantes sont stockées dans
delayed: VecDequepuis réveillées quand un input arrive (équivalent duwl_display_dispatch_pendingWayland)
Réutilisable pour le compositor Wayland :
- Le pattern EventQueue avec sources typées (
user_data!macro) est exactement ce qu'il faut pour le compositor Wayland - Le mécanisme
delayedpour les reads bloquants est réutilisable tel quel
1.3 Protocole orbital: (le scheme)
Implémenté dans core/mod.rs::OrbitalHandler::SchemeSync et scheme.rs (1721 lignes).
API client (ce qu'un client appelle pour ouvrir une fenêtre) :
open("/scheme/orbital/<flags>/<x>/<y>/<w>/<h>/<title>")
→ returns window_fd
write(window_fd, "T,nouveau titre") → titre
write(window_fd, "S,800,600") → resize
write(window_fd, "P,100,200") → position
write(window_fd, "Y,0,0,800,600,...") → damage rectangles
write(window_fd, "F,t,1") → flag transparent on
read(window_fd, &mut events) → pull events (clavier, souris, ...)
mmap_prep(window_fd, ...) → obtient un buffer mmap zero-copy
fsync(window_fd) → commit (équivalent wl_surface.commit)
Concepts à transposer en Wayland :
| Orbital | Équivalent Wayland |
|---|---|
| open() avec path verbeux | xdg_surface + xdg_toplevel configure |
| write("S,...") resize | xdg_toplevel.configure + ack |
| write("Y,...") damage | wl_surface.damage_buffer |
| mmap_prep | wl_shm_pool.create_buffer + wl_surface.attach |
| fsync | wl_surface.commit |
| read events | event queue Wayland |
Limites du protocole Orbital :
- API basée sur strings dans les writes — pas type-safe, pas de versioning
- Une seule sémantique d'extension (préfixes "A","D","F","M","P","S","T","Y")
- Pas de négociation de capabilities côté serveur
- Buffer mmap'é direct — moins flexible que
wl_shm_poolmais plus rapide
1.4 Composition (compositor.rs, 281 lignes)
Compositor logiciel CPU pur :
Image::roi_mut()pour écrire dans le framebufferColorARGB8888- Damage rectangles propagés aux clients via
Y,... - Curseur SW si pas de hardware cursor disponible (cf
core/display.rs:140set_client_capability(CursorPlaneHotspot, true))
Réutilisable directement : la logique damage tracking + composition CPU
est exactement ce qu'il faut pour la phase 6-7 du plan (wl_shm + composition).
2. Stack graphique Redox
2.1 API graphics-ipc (la lib commune)
base/drivers/graphics/graphics-ipc/src/lib.rs (127 lignes).
Découverte critique (commentaire ligne 13-15) :
The v2 graphics API allows creating framebuffers on the fly, using them for page flipping and handles all displays using a single fd. This is basically a subset of the Linux DRM interface with a couple of custom ioctls in the place of the KMS ioctls that are missing.
Conséquence : Redox a une API DRM compatible Linux (subset KMS).
La crate Rust drm upstream fonctionne directement sur Redox.
API exposée :
V2GraphicsHandle::from_file(file)
├─ resource_handles() ← liste connectors/encoders/CRTCs
├─ get_connector(handle, force_probe)
├─ get_encoder(handle)
├─ create_dumb_buffer(size, fourcc, bpp)
├─ map_dumb_buffer(buffer) ← mmap CPU-accessible
├─ add_framebuffer(buffer, depth, bpp)
├─ set_crtc(crtc, fb, position, connectors, mode)
├─ dirty_framebuffer(fb, &[ClipRect]) ← damage flush
├─ move_cursor / set_cursor2
└─ destroy_*
CpuBackedBuffer (lignes 46-127) :
- Wrapper sur
DumbBufferDRM - Optionnel : shadow buffer host (write-combining mitigation)
sync_rect()pour copier shadow → on-screen par damage
Implications pour le portage Wayland :
- Pas besoin de réinventer le display backend — l'API DRM existe
- Peut être utilisée telle quelle par un compositor Wayland Rust
CpuBackedBuffer::shadow_buf()retourne&mut [u8]— exactement le format SHM que Wayland attend pour la composition
2.2 Drivers graphiques disponibles
Localisation : base/drivers/graphics/.
| Driver | Cible | Statut | Notes |
|---|---|---|---|
vesad (133 + 275 lignes) |
VESA framebuffer firmware (BIOS/UEFI) | Stable | Lit FRAMEBUFFER_* env, support multi-FB |
virtio-gpud (615 + 528 lignes) |
virtio-gpu (QEMU/KVM) | Actif | C'est ce qui tourne sur ton image desktop |
ihdgd |
Intel HD Graphics | Actif | Driver natif HW |
fbcond |
Console framebuffer | — | Texte console |
fbbootlogd |
Boot log framebuffer | — | Affichage early boot |
console-draw |
Helpers dessin console | — | Lib commune |
driver-graphics |
Couche d'abstraction commune (GraphicsScheme) |
— | C'est elle qui exporte display.<driver> |
Tous publient leur scheme sous forme display.<nom> (ex: display.vesa).
2.3 Chemin d'ouverture du display
Orbital
└─> ConsumerHandle::new_vt() // /scheme/input/consumer
└─> open_display_v2()
└─> fpath() pour récupérer le path complet
└─> open("/scheme/.../v2/<display>") // fd graphics-ipc v2
└─> V2GraphicsHandle::from_file
C'est inputd qui détient la connaissance du driver graphique actif et
expose un chemin standard. Orbital ne hard-code pas vesa ou virtio-gpu —
il demande à inputd.
Implication pour le compositor Wayland : suivre le même pattern.
Demander à inputd quel display est associé au VT, ouvrir le fd retourné,
le wrapper en V2GraphicsHandle. Pas de hardcode de driver.
2.4 vesad — le chemin firmware framebuffer
base/drivers/graphics/vesad/src/main.rs (133 lignes).
Bootstrap (lignes 19-44) :
FRAMEBUFFER_WIDTH // hex string, ex "780" → 1920
FRAMEBUFFER_HEIGHT // ex "438" → 1080
FRAMEBUFFER_ADDR // adresse physique du FB fournie par firmware
FRAMEBUFFER_STRIDE // bytes par ligne
Le bootloader (UEFI/BIOS) place ces variables avant de chainer vers le kernel.
vesad mappe l'adresse physique en mémoire userspace et expose le FB via
GraphicsScheme.
Fallback bootloader env (lignes 60-84) : vesad lit /scheme/sys/env
pour FRAMEBUFFER1, FRAMEBUFFER2, ... — support multi-écran natif au boot
si le firmware en remonte plusieurs.
Implication : pour la phase 4 du plan (backend display), partir de vesad
comme chemin de validation initial = sûr et simple. virtio-gpud est plus
puissant mais plus complexe (gpu commandes, virgl optionnel).
3. Stack input
3.1 inputd — le multiplexer
base/drivers/inputd/src/{lib.rs,main.rs} (211 + 663 lignes).
Schemes exposés :
| Path | Pour | Rôle |
|---|---|---|
/scheme/input/consumer |
Orbital, futur compositor | reçoit les events triés (orbclient::Event) |
/scheme/input/consumer_bootlog |
bootlog | events early-boot |
/scheme/input/producer |
drivers ps2d, usbhidd | écrit des events bruts |
/scheme/input/control |
gestion VT/keymap | active VT, change keymap |
/scheme/input/handle/<scheme> |
délégation à un autre scheme | déléguer un VT à un autre serveur |
/scheme/input/handle_early/<scheme> |
idem mais avant init VT | bootlog, etc. |
API ConsumerHandle :
let h = ConsumerHandle::new_vt()?;
let display_fd = h.open_display_v2()?; // ← ouvre le display de ce VT
let evt_fd = h.event_handle(); // ← fd à mettre dans EventQueue
match h.read_events(&mut events)? {
ConsumerHandleEvent::Events(slice) => /* traite events */,
ConsumerHandleEvent::Handoff => /* VT change, on perd le contrôle */,
}
Le handoff via ESTALE est crucial : quand le VT switch (Ctrl-Alt-F2),
inputd retourne ESTALE — Orbital sait qu'il doit se mettre en veille
proprement. Le compositor Wayland devra gérer la même sémantique.
3.2 Drivers input
base/drivers/input/ :
ps2d— clavier/souris PS/2 (legacy + KVM)usbhidd— HID USB (clavier, souris, tablette)
Tous écrivent vers /scheme/input/producer. inputd dédoublonne, séquence,
attribue au VT actif, transmet au consumer.
3.3 Format d'event
orbclient::Event (struct C-compatible) — défini dans la crate orbclient.
Types : KeyEvent, MouseEvent, MouseRelativeEvent, ButtonEvent,
ScrollEvent, FocusEvent, QuitEvent, etc.
Pour Wayland :
- Mapping
orbclient::KeyEvent→wl_keyboard.key: direct - Codes de touches :
orbclientutilise des scancodes — il faudra traduire vers les keycodes XKB que Wayland attend - ⚠️ xkb keymap : à concevoir, voir section 5
4. Primitives OS pour Wayland (relibc)
Vérifications effectuées dans ~/Projets/Redox/relibc/src/.
4.1 Sockets Unix (AF_UNIX)
platform/redox/socket.rs :
- AF_UNIX bind/connect : implémenté via syscall direct (commentaire ligne 69 : "bind/connect with AF_UNIX were replaced with SYS_CALL")
- Path encoding :
chan:<path>(ligne 177 :buf.starts_with(b"chan:")) - SOCK_STREAM ✅ et SOCK_DGRAM ✅ supportés
- Compatible avec l'usage Wayland (
$XDG_RUNTIME_DIR/wayland-N)
4.2 fd passing — sendmsg / recvmsg avec SCM_RIGHTS
🟢 Critique : platform/redox/socket.rs :
- Lignes 272 et 447 :
(SOL_SOCKET, SCM_RIGHTS)traité dans cmsghdr - Lignes 835 et 924 :
recvmsg/sendmsgimplémentés en interne
C'est le pré-requis n°1 du plan (risque majeur 1) — il est rempli. Il faut quand même écrire des tests dédiés en phase 2 pour valider :
- Passage simple de fd entre deux processus
- Multiple fds dans un même cmsg
- Passage d'un fd shm + lecture côté receveur
4.3 Mémoire partagée — shm_open + mmap
shm_open : header/sys_mman/mod.rs:185 :
pub unsafe extern "C" fn shm_open(name, oflag, mode) -> c_int {
// traduit "/foo" → "/scheme/shm/foo" puis open() classique
}
Mécanisme : un scheme dédié /scheme/shm/ sert de namespace
(équivalent /dev/shm Linux mais via le scheme system).
mmap MAP_SHARED : présent (header/sys_mman/mod.rs). Tous les buffers
DRM dumb sont déjà mappés ainsi par graphics-ipc.
4.4 ⚠️ memfd_create
- Numéro syscall défini :
__NR_memfd_create = 319(x86_64) - Implémentation : pas vue dans la sortie grep — probablement absente ou stub
- Impact pour Wayland : libwayland-client moderne préfère
memfd_createpour les shm pools (pas de path needed). Fallback :shm_openavec nom unique → fonctionne, juste un peu plus verbeux
À traiter en phase 2 :
- Soit implémenter
memfd_createau-dessus deshm_open + shm_unlink - Soit ajouter une couche
cfg(target_os = "redox")côtéwayland-clientqui force le path shm_open
4.5 Event loop / poll
header/poll/mod.rs:poll()POSIX disponibleheader/sys_select/mod.rs:selectPOSIXheader/sys_epoll/mod.rs:epoll_*(probablement émulé sur Redox via l'EventQueue native — à vérifier)- Native Redox :
redox_event::EventQueue— utilisé par Orbital, plus idiomatique. Pour le compositor Rust pur, autant l'utiliser directement plutôt que de passer par poll() POSIX.
5. Manques identifiés (à traiter dans le plan)
5.1 Pas de keymap XKB sur Redox
Wayland exige que le serveur envoie un keymap XKB au client (wl_keyboard.keymap
event, format XKB_V1). Or :
- Redox utilise des scancodes orbclient
- Pas de
xkbcommonpackagé sur Redox (à confirmer en cherchant la recette) - Pas de fichiers de keymap XKB système
À traiter en phase 5 (backend input) :
- Option A : porter
libxkbcommon(C, ~10k loc) - Option B : utiliser la crate Rust
xkb(wrapper xkbcommon, dépend du C) - Option C : implémenter un sous-ensemble XKB en Rust (plus long mais cohérent avec l'esprit du projet)
Recommandation : Option C mais avec scope minimal (US layout + variantes
basiques) au début. La crate xkeysym peut servir de base.
5.2 Pas d'AT-SPI / dbus pour l'accessibilité
- Phase 11 du plan vise navigation clavier + métadata d'accessibilité
- Sur Linux, AT-SPI transporte ces métadata via dbus
- Dbus existe sur Redox mais portage limité ; AT-SPI n'est pas porté
- À concevoir : protocole Redox simple d'accessibilité, ou wayland-protocols custom (text-input-v3 comme point de départ)
5.3 GPU userspace driver manquant
- vesad et virtio-gpud existent mais pas de DRM driver "GPU complet" hors virtio
- Mesa3D Redox = LLVMpipe seulement (CPU)
- Phase 12 du plan = GPU expérimental — restera CPU pour le MVP
- À documenter : aucune accélération hardware n'est garantie pour les phases 0-11
5.4 Pas de session manager / VT API stable
- Sur Linux :
logind/seatdgèrent les VT et l'accès aux devices - Sur Redox :
inputdjoue un rôle similaire mais pas équivalent - Pour Smithay (phase 13), il faudra un backend session Redox basé sur inputd
6. Ce qui est réutilisable directement
| Composant Redox actuel | Usage dans le compositor Wayland |
|---|---|
redox_event::EventQueue |
Boucle principale du compositor |
redox-scheme::SchemeSync |
Si on choisit aussi de publier un scheme wayland: |
graphics-ipc::V2GraphicsHandle |
Backend display (phase 4) — direct |
graphics-ipc::CpuBackedBuffer |
wl_shm composition (phase 6) — direct |
inputd::ConsumerHandle |
Backend input (phase 5) — direct |
orbital/src/compositor.rs damage tracking |
Référence pour notre damage logic (phase 6-7) |
orbital/src/scheme.rs focus + raccourcis |
Référence pour focus management (phase 7) |
redox-log |
Logging |
Crate drm upstream |
Si on veut adresser DRM directement |
7. Décisions recommandées pour la suite
Phase 2 (primitives OS) — peut être réduite
Plutôt que d'auditer toutes les primitives, se limiter à des tests dédiés :
- Test fd passing : 2 processus, l'un crée un memfd-like, l'autre le mappe
- Test Unix socket SOCK_STREAM avec messages Wayland-shaped (header binaire)
- Test event loop multi-fd avec signaux POSIX
- Test concurrent shm_open/mmap depuis plusieurs processus
Si les 4 tests passent, on a la garantie que wayland-rs peut tourner.
Estimation : 1 mois à 2h/jour au lieu des 6 mois initialement budgétés.
Phase 3 (port wayland-rs) — à découper
wayland-rs upstream a peu de deps OS-specifiques dans son crate wayland-backend.
Ordre suggéré :
wayland-scanner(génération code XML → Rust) : pure logic, devrait marcher tel quelwayland-backend: couche socket — vérifier lecfg(unix)vs ajout d'uncfg(target_os = "redox")wayland-server: haut niveau — devrait fonctionner si backend OKwayland-client: symétrique
Phase 4 (display backend) — voie rapide possible
V2GraphicsHandle est si proche de l'API DRM Linux qu'on peut s'inspirer
directement de core/display.rs d'Orbital pour le RedoxOutput.
Estimation : 2 mois à 2h/jour (au lieu des 6 mois si on partait de zéro).
8. Repos clonés localement pour la suite
~/Projets/Redox/
├── orbital/ ← référence compositor (gitlab.redox-os.org/redox-os/orbital)
├── base/ ← drivers + graphics-ipc + inputd (gitlab.redox-os.org/redox-os/base)
├── relibc/ ← libc Redox, primitives POSIX (--depth 1)
├── redox-src/ ← repo umbrella, ~/Projets/Redox/redox-src/build/x86_64/desktop/harddrive.img
└── docs/existing-redox-gui.md ← ce document
Sources additionnelles à cloner si on creuse plus :
redox-os/wayland-rs-redox-fork(à créer le moment venu)redox-os/drivers(déjà inclus dans base/drivers/)Smithay/smithay(plus tard, phase 13)
9. Documents à produire ensuite
Selon le plan directeur (section "Documents A Produire Ensuite") :
| Document | Quand | Contenu |
|---|---|---|
redox-wayland-primitives.md |
Phase 2, après tests | Résultats des 4 tests dédiés + conclusions |
compositor-architecture.md |
Phase 3-4 | Crates, traits, flux de données |
display-backend-redox.md |
Phase 4 | Détails RedoxOutput + dirty_framebuffer flow |
input-backend-redox.md |
Phase 5 | Mapping orbclient → Wayland + XKB strategy |
software-rendering-and-gpu-roadmap.md |
Phase 4 + 12 | CPU paths + GPU horizon |
accessibility-roadmap.md |
Phase 11 | Décisions sans AT-SPI |
orbital-migration.md |
Phase 8-9 | Comment porter winit/softbuffer/clients |
cosmic-smithay-roadmap.md |
Phase 13 | Quand y aller, dépendances bloquantes |
x11-compat-rust-roadmap.md |
Phase 14 | Projet séparé |
Fin de l'audit phase 1.