diff options
| -rw-r--r-- | crates/config/src/engine/support.rs | 10 | ||||
| -rw-r--r-- | crates/core/src/manager/mod.rs | 18 | ||||
| -rw-r--r-- | crates/srdwm/src/main.rs | 2 | ||||
| -rw-r--r-- | crates/wayland/src/udev/gpu.rs | 34 | ||||
| -rw-r--r-- | crates/wayland/src/udev/platform.rs | 24 |
5 files changed, 65 insertions, 23 deletions
diff --git a/crates/config/src/engine/support.rs b/crates/config/src/engine/support.rs index b67a688..9f7e537 100644 --- a/crates/config/src/engine/support.rs +++ b/crates/config/src/engine/support.rs @@ -144,6 +144,16 @@ pub(super) fn default_config() -> HashMap<String, ConfigValue> { set("general.animation_duration", Number(200.0)); set("general.shadows", Bool(true)); set("general.resize_margin", Number(6.0)); + // `false`: real GBM+EGL+`DrmCompositor` GPU rendering on the udev + // backend is opt-in and still missing real window content/decoration + // support (see `crates/wayland/src/udev/gpu.rs`'s own module doc + // comment for exactly what it does render) - unlike `general. + // rounded_corners` just above, this has one unambiguous default + // regardless of which backend ends up connecting (GPU rendering is + // udev-only and experimental everywhere), so it's seeded here like + // every other ordinary flag rather than left absent for a backend to + // decide. + set("general.gpu", Bool(false)); // Deliberately *not* seeded here, unlike every other `general.*` key -- // its actual default differs by backend (GLES/winit: on; udev/Pixman: // off, an untested-on-real-hardware CPU cost too real to default to on diff --git a/crates/core/src/manager/mod.rs b/crates/core/src/manager/mod.rs index 74be06b..9593dd3 100644 --- a/crates/core/src/manager/mod.rs +++ b/crates/core/src/manager/mod.rs @@ -189,6 +189,23 @@ pub struct WindowManager { /// redraws constantly - see `crates/wayland/src/rounded_corners.rs`). /// `Some(_)` only when the user explicitly set it, and wins either way. pub rounded_corners_enabled: Option<bool>, + /// Whether the udev backend attempts real GBM+EGL+`DrmCompositor` GPU + /// rendering instead of the default, always-available software + /// (Pixman/dumb-buffer) path - read from `general.gpu`, `false` by + /// default (unlike `rounded_corners_enabled`'s `Option`, this has one + /// unambiguous default regardless of backend: GPU rendering is udev- + /// only and experimental everywhere, so "off" is correct whether or + /// not the eventual backend even has a GPU path at all). `true` here + /// only ever *attempts* it - `udev::gpu::probe` still falls back to + /// the untouched software path on any failure at any step (no GBM + /// device, no atomic-modesetting support, a software-only EGL + /// renderer, ...), logged but never fatal, so setting this on a + /// machine or VM without real GPU/KMS support costs nothing beyond + /// the one failed probe at startup. `SRDWM_GPU=1` (an env var, unset + /// by default) remains a separate, lower-level override for testing + /// without touching config - `udev::platform::connect` attempts the + /// probe if *either* this or the env var says to. + pub gpu_enabled: bool, /// The whole-screen colour treatment currently active (night light's /// warm tint or reading mode's desaturation), live-settable via `srd /// set night_light`/`srd set reading_mode` - see [`ColorFilter`]. Off @@ -349,6 +366,7 @@ impl WindowManager { shadows_enabled: true, resize_margin: RESIZE_MARGIN, rounded_corners_enabled: None, + gpu_enabled: false, color_filter: ColorFilter::None, focus_follows_mouse: false, auto_raise: false, diff --git a/crates/srdwm/src/main.rs b/crates/srdwm/src/main.rs index 1f33a74..a229d34 100644 --- a/crates/srdwm/src/main.rs +++ b/crates/srdwm/src/main.rs @@ -171,6 +171,7 @@ fn apply_general_settings(engine: &Engine, wm: &Rc<RefCell<WindowManager>>) { // - see `WindowManager::rounded_corners_enabled`'s doc comment for why // this can't just be `get_bool(..., true)` like every other flag here. let rounded_corners = engine.get("general.rounded_corners").and_then(|v| v.as_bool()); + let gpu = engine.get_bool("general.gpu", false); let focus_follows_mouse = engine.get_bool("general.focus_follows_mouse", false); let auto_raise = engine.get_bool("general.auto_raise", false); @@ -295,6 +296,7 @@ fn apply_general_settings(engine: &Engine, wm: &Rc<RefCell<WindowManager>>) { wm.shadows_enabled = shadows; wm.resize_margin = resize_margin; wm.rounded_corners_enabled = rounded_corners; + wm.gpu_enabled = gpu; wm.focus_follows_mouse = focus_follows_mouse; wm.auto_raise = auto_raise; wm.theme = theme; diff --git a/crates/wayland/src/udev/gpu.rs b/crates/wayland/src/udev/gpu.rs index 904a420..8617af1 100644 --- a/crates/wayland/src/udev/gpu.rs +++ b/crates/wayland/src/udev/gpu.rs @@ -1,6 +1,7 @@ -//! Opt-in (`SRDWM_GPU=1`) GBM+EGL+`DrmCompositor` GPU render path for the -//! udev backend - see [`probe`]'s own doc comment for exactly what this -//! does and does not do yet. Past the original Phase 2 (one output, +//! Opt-in (`general.gpu` in config, or the lower-level `SRDWM_GPU=1` env +//! var) GBM+EGL+`DrmCompositor` GPU render path for the udev backend -- +//! see [`probe`]'s own doc comment for exactly what this does and does +//! not do yet. Past the original Phase 2 (one output, //! clear-color only - see the plan this was built from, `snappy- //! percolating-boole.md`, for that phase's own scoping): every head //! `initialize_output` succeeds for gets driven, not just the first @@ -106,15 +107,20 @@ impl GpuContext { const COLOR_FORMATS: [DrmFourcc; 2] = [DrmFourcc::Argb8888, DrmFourcc::Xrgb8888]; /// Attempts the full GBM+EGL+GLES+`DrmDevice`+`DrmOutputManager` chain -/// against `card`'s DRM fd, gated behind `SRDWM_GPU=1` (unset - the -/// default - skips this entirely: zero cost, zero risk, identical to -/// every session before this one). Returns `None` on *any* failure at any -/// step, each logged with which step failed and why, so a machine without -/// working KMS+3D driver support (or a VM with only dumb-buffer scanout -- -/// this backend's own long-standing default target, see `udev/mod.rs`'s -/// module doc comment) gets one clear, harmless log line instead of -/// anything touching the actual rendering/modesetting this backend already -/// does. +/// against `card`'s DRM fd, gated behind `enabled` (the caller's own +/// combined decision - `udev/platform.rs`'s call site attempts this +/// whenever *either* `general.gpu` in config or the lower-level +/// `SRDWM_GPU=1` env-var override says to; both unset/`false` is the +/// default, and skips this entirely: zero cost, zero risk, identical to +/// every session before this option existed). Returns `None` on *any* +/// failure at any step, each logged with which step failed and why, so a +/// machine without working KMS+3D driver support (or a VM with only +/// dumb-buffer scanout - this backend's own long-standing default +/// target, see `udev/mod.rs`'s module doc comment) gets one clear, +/// harmless log line instead of anything touching the actual rendering/ +/// modesetting this backend already does, and falls straight back to +/// that same always-available software path with no further action +/// needed from whoever enabled this. /// /// `DrmDevice::new`'s own `disable_connectors` parameter (passed `false` /// here, matching the existing legacy path's own connector handling) is @@ -132,8 +138,8 @@ const COLOR_FORMATS: [DrmFourcc; 2] = [DrmFourcc::Argb8888, DrmFourcc::Xrgb8888] /// is building a ready-to-use `GpuContext`; which head (if any) actually /// gets driven through it is a per-session, per-head decision the caller /// (`udev/platform.rs`'s startup path) makes once this succeeds. -pub(crate) fn probe(card: &Card) -> Option<(GpuContext, DrmDeviceNotifier)> { - if std::env::var("SRDWM_GPU").as_deref() != Ok("1") { +pub(crate) fn probe(card: &Card, enabled: bool) -> Option<(GpuContext, DrmDeviceNotifier)> { + if !enabled { return None; } // One `DrmDeviceFd` used for everything below - GBM, EGL, and the diff --git a/crates/wayland/src/udev/platform.rs b/crates/wayland/src/udev/platform.rs index 19991e8..691c8de 100644 --- a/crates/wayland/src/udev/platform.rs +++ b/crates/wayland/src/udev/platform.rs @@ -36,15 +36,21 @@ impl UdevPlatform { .open(&gpu_path, rustix::fs::OFlags::RDWR | rustix::fs::OFlags::CLOEXEC) .map_err(err)?; let card = Rc::new(Card(fd)); - // Opt-in only (`SRDWM_GPU=1`, unset by default) - see `gpu::probe`'s - // own doc comment for exactly what this does and does not do yet. - // A no-op unless that variable is set, so this line changes nothing - // about any session that doesn't set it. `gpu_notifier` is - // registered as its own calloop event source further down - // (alongside `register_drm_fd`'s own registration for the - // existing legacy heads); `gpu_context` is stored on `UdevState` - // below and consulted by `render_udev_frame`. - let (mut gpu_context, gpu_notifier) = match super::gpu::probe(&card) { + // Opt-in only - `general.gpu` in config (`wm.gpu_enabled`, + // `false` by default) or the lower-level `SRDWM_GPU=1` env var, + // whichever says yes - see `gpu::probe`'s own doc comment for + // exactly what this does and does not do yet. A no-op unless + // either says to, so this line changes nothing about any session + // that leaves both alone. The env var stays as a quick manual + // override for testing without touching config (still works even + // if `general.gpu` is explicitly `false`) - it does not gate + // config *off*, only ever adds an extra way to opt *in*. + // `gpu_notifier` is registered as its own calloop event source + // further down (alongside `register_drm_fd`'s own registration + // for the existing legacy heads); `gpu_context` is stored on + // `UdevState` below and consulted by `render_udev_frame`. + let gpu_enabled = wm.borrow().gpu_enabled || std::env::var("SRDWM_GPU").as_deref() == Ok("1"); + let (mut gpu_context, gpu_notifier) = match super::gpu::probe(&card, gpu_enabled) { Some((ctx, notifier)) => (Some(ctx), Some(notifier)), None => (None, None), }; |