From c6ad583a725ab616723a5b988ca77abe8fc0f493 Mon Sep 17 00:00:00 2001 From: Votre Nom Date: Fri, 8 May 2026 19:36:07 +0200 Subject: [PATCH] Phase 4.1-4.3 : test display backend Redox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Crate redox-wl-test-display-backend qui réutilise le pattern Orbital : inputd::ConsumerHandle::new_vt() → open_display_v2() → V2GraphicsHandle. Comportement vérifié : - compile pour x86_64-unknown-redox sans patch (graphics-ipc, inputd, drm via git deps gitlab.redox-os.org/redox-os/base.git, comme Orbital) - sous redoxer run headless : ConsumerHandle::new_vt() OK, open_display_v2 retourne EINVAL (cohérent avec absence framebuffer) - runtime sur framebuffer (redoxer --gui ou make qemu) : à valider manuellement par le user (la fenêtre QEMU étant interactive) README enrichi avec la marche à suivre pour les tests display (voie A: redoxer exec --gui ; voie B: redoxfs + make qemu). Leyoda 2026 – GPLv3 --- README.md | 34 ++++- .../redox-wl-test-display-backend/Cargo.toml | 11 ++ .../redox-wl-test-display-backend/src/main.rs | 141 ++++++++++++++++++ 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 crates/redox-wl-test-display-backend/Cargo.toml create mode 100644 crates/redox-wl-test-display-backend/src/main.rs diff --git a/README.md b/README.md index 7a97e32..e90de09 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ fd reçu — pixel-perfect. │ ├── redox-wl-test-poll-multifd/ # primitive 4 : poll() multiplexing + POLLHUP │ ├── redox-wl-poc-pixels/ # POC : datapath shm + SCM_RIGHTS bout en bout │ ├── redox-wl-test-handshake/ # phase 3 : wayland-rs server/client registry -│ └── redox-wl-test-shm-pipeline/ # phase 3 : pipeline shm complet validé +│ ├── redox-wl-test-shm-pipeline/ # phase 3 : pipeline shm complet validé +│ └── redox-wl-test-display-backend/ # phase 4.1 : ouvre display Redox via inputd + V2GraphicsHandle └── (pas de Cargo.toml racine : chaque crate est standalone — voir note ci-dessous) ``` @@ -59,6 +60,37 @@ Pattern attendu en fin d'exécution : `[test-XX] PASS: ...`. > qui fait un fail au link (`undefined reference CMSG_NXTHDR/CMSG_DATA`) parce que le linker host > ne sait pas chaîner librelibc.a du sysroot Redox. `redoxer` configure le linker correctement. +## Tests qui exigent un vrai framebuffer + +Les binaires qui touchent au display (à partir de `redox-wl-test-display-backend`) +ne tourneront pas sous `redoxer run` standard car celui-ci est headless. +Deux voies pour les exécuter : + +### Voie A — `redoxer exec --gui` (mini-VM interactive) +```bash +cd crates/redox-wl-test-display-backend +redoxer build --release +redoxer exec --gui target/x86_64-unknown-redox/release/redox-wl-test-display-backend +``` +Ouvre une fenêtre QEMU, boote une mini-VM Redox avec framebuffer, lance le binaire. +À fermer manuellement quand le test est fini. + +### Voie B — Image complète + `make qemu` +Pousser le binaire dans une image Redox bootable via redoxfs-fuse : +```bash +# Monter l'image +sudo modprobe fuse +mkdir -p /tmp/redox-mnt +redoxfs ~/Projets/Redox/redox-src/build/x86_64/desktop/harddrive.img /tmp/redox-mnt +# Copier le binaire +sudo cp target/x86_64-unknown-redox/release/redox-wl-test-display-backend /tmp/redox-mnt/usr/bin/ +# Démonter +fusermount -u /tmp/redox-mnt +# Booter +cd ~/Projets/Redox/redox-src && make qemu audio=no +# Dans Redox : login user / password root, puis lancer le binaire +``` + ## Roadmap Voir `REDOX_COSMIC_XWAYLAND_RS_PLAN.md` pour le plan complet 14 phases / 5 ans. diff --git a/crates/redox-wl-test-display-backend/Cargo.toml b/crates/redox-wl-test-display-backend/Cargo.toml new file mode 100644 index 0000000..2ed61e2 --- /dev/null +++ b/crates/redox-wl-test-display-backend/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "redox-wl-test-display-backend" +version = "0.1.0" +edition = "2021" + +[dependencies] +drm = "0.15" +graphics-ipc = { git = "https://gitlab.redox-os.org/redox-os/base.git" } +inputd = { git = "https://gitlab.redox-os.org/redox-os/base.git" } +libredox = "0.1" +orbclient = "0.3" diff --git a/crates/redox-wl-test-display-backend/src/main.rs b/crates/redox-wl-test-display-backend/src/main.rs new file mode 100644 index 0000000..699ef8c --- /dev/null +++ b/crates/redox-wl-test-display-backend/src/main.rs @@ -0,0 +1,141 @@ +//! Phase 4 — Test display backend Redox. +//! +//! Premier binaire qui touche au display Redox. Réutilise exactement le pattern +//! d'Orbital (cf orbital/src/core/mod.rs et core/display.rs) : +//! +//! inputd::ConsumerHandle::new_vt() +//! └─> open_display_v2() +//! └─> graphics_ipc::V2GraphicsHandle::from_file +//! └─> drm::Device + drm::control::Device (subset KMS Redox) +//! +//! Comportement attendu selon environnement : +//! +//! - sous `redoxer run` (headless, pas de framebuffer) : ConsumerHandle::new_vt() +//! ouvre /scheme/input/consumer, mais open_display_v2 va probablement échouer +//! parce que vesad/virtio-gpud n'a pas de display à offrir. On capture l'erreur. +//! +//! - dans une vraie session Redox bootée via `make qemu` (avec framebuffer) : +//! le display s'ouvre, on énumère les connecteurs et modes. Si on a au moins +//! un display connecté, on alloue un CpuBackedBuffer ARGB et on dessine un +//! pattern dedans. Note : on ne fait PAS encore de modeset (pas de set_crtc) +//! parce qu'Orbital tient déjà le display. Ce test reste lecture seule à ce +//! stade — phase 4 vraie consiste à *prendre la place* d'Orbital. + +use std::io; +use std::process::ExitCode; + +use drm::Device as _; +use drm::control::{Device as _, connector::State}; +use graphics_ipc::V2GraphicsHandle; +use inputd::ConsumerHandle; + +fn run() -> Result<(), Box> { + println!("[disp] Phase 4 display backend test on Redox"); + + // Step 1: open consumer handle (talks to inputd) + let consumer = ConsumerHandle::new_vt().map_err(|e| { + format!( + "ConsumerHandle::new_vt failed (expected in headless redoxer): {e} \ + (errno {})", + io::Error::last_os_error().raw_os_error().unwrap_or(0) + ) + })?; + println!("[disp] inputd consumer handle opened"); + + // Step 2: open display via inputd's fpath redirection + let display_file = consumer.open_display_v2().map_err(|e| { + format!( + "open_display_v2 failed (expected in headless redoxer): {e}" + ) + })?; + println!("[disp] display file opened from inputd path"); + + // Step 3: wrap as V2GraphicsHandle (subset DRM Linux) + let handle = V2GraphicsHandle::from_file(display_file)?; + println!("[disp] V2GraphicsHandle created"); + + // Step 4: enumerate connectors + let resources = handle.resource_handles()?; + let connectors = resources.connectors(); + println!("[disp] {} connector(s) reported by KMS subset", connectors.len()); + + let mut connected_count = 0; + for (i, &conn) in connectors.iter().enumerate() { + match handle.get_connector(conn, true) { + Ok(info) => { + let state = info.state(); + let modes = info.modes(); + println!( + "[disp] #{i} connector {:?}: state={:?}, {} mode(s)", + conn, + state, + modes.len() + ); + if state == State::Connected { + connected_count += 1; + if let Some(mode) = modes.first() { + let (w, h) = mode.size(); + println!("[disp] first mode: {w}x{h}"); + } + } + } + Err(e) => { + eprintln!("[disp] #{i} connector {:?}: get_connector failed: {e}", conn); + } + } + } + + if connected_count == 0 { + return Err("no connected display found".into()); + } + println!("[disp] {connected_count} connected display(s)"); + + // Step 5: capabilities probe + use drm::DriverCapability; + let dumb = handle.get_driver_capability(DriverCapability::DumbBuffer); + let cursor_w = handle.get_driver_capability(DriverCapability::CursorWidth); + let cursor_h = handle.get_driver_capability(DriverCapability::CursorHeight); + println!( + "[disp] driver caps: dumb_buffer={:?} cursor={}x{}", + dumb, + cursor_w.map(|v| v.to_string()).unwrap_or_else(|_| "?".into()), + cursor_h.map(|v| v.to_string()).unwrap_or_else(|_| "?".into()), + ); + + // Step 6: try allocating a CpuBackedBuffer of a small size, paint a pattern, + // and destroy it. This validates the buffer pipeline of graphics-ipc without + // setting it as scanout (which would require a CRTC takeover from Orbital). + use drm::buffer::DrmFourcc; + use graphics_ipc::CpuBackedBuffer; + let (test_w, test_h) = (64u32, 64u32); + let mut buf = CpuBackedBuffer::new(&handle, (test_w, test_h), DrmFourcc::Argb8888, 32)?; + println!( + "[disp] CpuBackedBuffer allocated {}x{} ARGB8888 (shadow={})", + test_w, + test_h, + buf.has_shadow_buf() + ); + let bytes = buf.shadow_buf(); + for (i, b) in bytes.iter_mut().enumerate() { + *b = (i & 0xFF) as u8; + } + buf.sync_rect(0, 0, test_w, test_h); + println!("[disp] painted test pattern + sync_rect"); + buf.destroy(&handle)?; + println!("[disp] CpuBackedBuffer destroyed"); + + Ok(()) +} + +fn main() -> ExitCode { + match run() { + Ok(()) => { + println!("[disp] PASS: display backend pipeline reachable"); + ExitCode::SUCCESS + } + Err(e) => { + eprintln!("[disp] FAIL: {e}"); + ExitCode::FAILURE + } + } +}