srdusr
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-05-28 09:42:00 +0200
committersrdusr <[email protected]>2025-05-28 09:42:00 +0200
commit6a9e50280ad8262e9fe49e390527e7490564f8dd (patch)
tree6911dbfe68ac983c228b5c9fc9320beae42b6e6a
parentd0103908bd1c316bdebaa48e13aae332cffdeabf (diff)
downloadsrdwm-6a9e50280ad8262e9fe49e390527e7490564f8dd.tar.gz
srdwm-6a9e50280ad8262e9fe49e390527e7490564f8dd.zip
Add a real general.gpu config option for the GPU render path
SRDWM_GPU=1 was the only way to opt into the udev backend's GBM+EGL GPU render path - an env var, not a real config option, with no way to enable it from init.lua the way every other general.* flag works. WindowManager::gpu_enabled (plain bool, false by default - unlike rounded_corners_enabled's Option<bool>, GPU rendering has one unambiguous default regardless of which backend ends up connecting, so there's no "let the backend decide" case to preserve) is read from general.gpu in apply_general_settings, same as every other general.* key. gpu::probe now takes an explicit enabled: bool instead of checking the env var itself; udev/platform.rs's call site computes it as wm.gpu_enabled OR SRDWM_GPU=1, so the env var still works as a quick manual override for testing without touching config, on top of the new persistent option. Falls back to the existing software (Pixman) path exactly as before on any failure at any step (no GBM device, no atomic-modesetting support, a software-only EGL renderer, ...) - gpu::probe's own fallback behavior is unchanged, only how the initial enabled/disabled decision gets made.
-rw-r--r--crates/config/src/engine/support.rs10
-rw-r--r--crates/core/src/manager/mod.rs18
-rw-r--r--crates/srdwm/src/main.rs2
-rw-r--r--crates/wayland/src/udev/gpu.rs34
-rw-r--r--crates/wayland/src/udev/platform.rs24
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),
};