diff options
| -rw-r--r-- | crates/wayland/src/udev/gpu.rs | 17 | ||||
| -rw-r--r-- | crates/wayland/src/udev/render.rs | 45 | ||||
| -rw-r--r-- | docs/DEFAULTS.md | 13 | ||||
| -rw-r--r-- | docs/IMPLEMENTATION_STATUS.md | 9 |
4 files changed, 56 insertions, 28 deletions
diff --git a/crates/wayland/src/udev/gpu.rs b/crates/wayland/src/udev/gpu.rs index 8617af1..7b06ae3 100644 --- a/crates/wayland/src/udev/gpu.rs +++ b/crates/wayland/src/udev/gpu.rs @@ -6,10 +6,19 @@ //! percolating-boole.md`, for that phase's own scoping): every head //! `initialize_output` succeeds for gets driven, not just the first //! (`GpuContext::outputs`), VT-switch pause/activate is wired -//! (`udev/session.rs`'s `SessionEvent` handlers), and the real cursor -//! renders on top of the clear color (`udev/render.rs`'s own GPU branch). -//! Window content and decorations are the remaining gap - a GPU-driven -//! head still shows no windows, just its own clear color and cursor. +//! (`udev/session.rs`'s `SessionEvent` handlers), and the real cursor and +//! real window content both render on top of the clear color +//! (`udev/render.rs`'s own GPU branch). Window content is plain +//! `surface_content_elements` - square corners, no border or titlebar -- +//! not yet the masked/rounded path the Pixman branch uses (built against +//! `PixmanRenderer` specifically) or the GLES shader `winit/render.rs` +//! already has for its own single-output case; decorations (border, +//! titlebar) are the remaining real gap. Untested on real GPU-enabled +//! hardware as of this writing - `SRDWM_GPU`/`general.gpu` were both +//! unset on the machine this was built on, so this compiles, passes the +//! full test suite, and matches the existing Pixman path's own per- +//! window geometry logic by inspection, but has not been visually +//! confirmed against a real compositor session with the flag on. use std::os::fd::{AsFd, OwnedFd}; diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs index 4d51fab..0250c8a 100644 --- a/crates/wayland/src/udev/render.rs +++ b/crates/wayland/src/udev/render.rs @@ -232,21 +232,36 @@ impl CompState { // field access, not a method call, even one that (like // this one) only actually touches `self.outputs`. if let Some(gpu_output) = gpu.outputs.iter_mut().find(|(c, _)| *c == head_crtc).map(|(_, o)| o) { - // The one real element this phase pushes: the same - // `cursor::render_elements` the Pixman path already - // uses, generic over the renderer (`R: Renderer + - // ImportAll + ImportMem`), so it works unmodified - // against `gpu.renderer` (`GlesRenderer`) instead of - // `udev.renderer` (`PixmanRenderer`). Window content - // and decorations are real, separate scope past this - // (they need either a GLES-side version of the - // border/titlebar bitmap upload path, or the rounded- - // corner GLES shader `winit/render.rs` already has - // wired for its own single-output case) - not - // attempted here, so a GPU-driven head still shows a - // plain clear color under its own real, moving cursor, - // not yet any windows. - let elements = crate::cursor::render_elements(&cursor_status, &cursor_buffers, &mut gpu.renderer, udev.pointer_pos, origin, udev.heads[index].size); + // Cursor first (topmost - `render_frame` draws + // earliest-pushed on top, same convention the Pixman + // path's own `custom_elements` uses), content after. + // `ids` is already front-to-back (topmost window + // first), and pushing in that same order is what + // makes plain painter's-algorithm draw order occlude + // correctly between windows, same as the Pixman + // path's own `custom_elements` relies on (see its own + // comment on `occluders` above). Plain + // `surface_content_elements` - unrounded, no + // decorations - not the masked/rounded path the + // Pixman branch uses (that's built against + // `PixmanRenderer` specifically) or the GLES shader + // `winit/render.rs` has (real, separate scope to wire + // in here too). A GPU-driven head shows real window + // content now, square corners and no border/titlebar, + // rather than none at all. + let mut elements: Vec<crate::elements::OverlayElement<smithay::backend::renderer::gles::GlesRenderer>> = + crate::cursor::render_elements(&cursor_status, &cursor_buffers, &mut gpu.renderer, udev.pointer_pos, origin, udev.heads[index].size); + for &id in &ids { + let Some(w) = self.wm.borrow().window(id).cloned() else { continue }; + let Some(dwindow) = self.id_to_window.get(&id) else { continue }; + let Some(surface) = crate::elements::window_wl_surface(dwindow) else { continue }; + let geom = self.window_anims.get(&id).map(crate::state::WindowAnim::current_rect).unwrap_or(w.geometry); + let band = if w.decorated { srdwm_core::TITLEBAR_HEIGHT as i32 } else { 0 }; + let raw_offset = dwindow.geometry().loc; + let content_offset = Point::<i32, Logical>::from((raw_offset.x.max(0), raw_offset.y.max(0))); + let pos = (geom.x - origin.x - content_offset.x, geom.y + band - origin.y - content_offset.y); + elements.extend(crate::elements::surface_content_elements(&mut gpu.renderer, &surface, pos, w.opacity)); + } let clear_color = [0.05, 0.05, 0.08, 1.0]; match gpu_output.render_frame(&mut gpu.renderer, &elements, clear_color, smithay::backend::drm::compositor::FrameFlags::DEFAULT) { Ok(res) if !res.is_empty => match gpu_output.queue_frame(None) { diff --git a/docs/DEFAULTS.md b/docs/DEFAULTS.md index ac18f7c..7e712c5 100644 --- a/docs/DEFAULTS.md +++ b/docs/DEFAULTS.md @@ -45,12 +45,13 @@ Read once at startup, not live-settable via `srd set` - the render backend is wired into the DRM pipeline when the compositor connects to its GPU, not something that can be swapped while running. -Still missing real window content and decorations as of this writing: -a GPU-driven head renders its own clear color and the real cursor, not -yet any windows - see `crates/wayland/src/udev/gpu.rs`'s own module -doc comment for the current state. `SRDWM_GPU=1` (an environment -variable) remains a separate, lower-level override for testing without -touching config - either it or `general.gpu` being set is enough to +Still missing decorations (border, titlebar) as of this writing: a +GPU-driven head renders its own clear color, the real cursor, and real +window content (plain, square-cornered, no border/titlebar) - see +`crates/wayland/src/udev/gpu.rs`'s own module doc comment for the +current state. `SRDWM_GPU=1` (an environment variable) remains a +separate, lower-level override for testing without touching config -- +either it or `general.gpu` being set is enough to attempt GPU rendering. ### Monitor Settings (`monitor.*`) diff --git a/docs/IMPLEMENTATION_STATUS.md b/docs/IMPLEMENTATION_STATUS.md index 3365831..6fe207b 100644 --- a/docs/IMPLEMENTATION_STATUS.md +++ b/docs/IMPLEMENTATION_STATUS.md @@ -159,9 +159,12 @@ once, so splitting it across three files would have hidden it. otherwise), falling back to the software path unchanged on any failure at any step. Every connected head it successfully initializes gets driven through it, VT-switch pause/activate is wired, and the - real cursor renders on top of its own clear color - window content - and decorations are the remaining gap: a GPU-driven head shows no - windows yet, only its clear color and cursor. + real cursor and real window content (plain, square-cornered, no + border/titlebar yet) both render on top of its own clear color -- + decorations are the remaining gap. Untested on real GPU-enabled + hardware as of this writing - builds and passes the full test suite, + but `SRDWM_GPU`/`general.gpu` were both unset on the machine this was + built on. `WaylandPlatform::connect` (winit) picks this backend automatically when no `WAYLAND_DISPLAY`/`DISPLAY` is set, falling back to nested winit if udev init fails for any reason. |