diff options
| author | srdusr <[email protected]> | 2024-07-09 14:43:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-07-09 14:43:00 +0200 |
| commit | d2952af18b907a5b18fccd26468a74aabe49bb2f (patch) | |
| tree | 9bc553b83eed57ff62e2cbe308e496f641d32d5b /crates/wayland/src/elements.rs | |
| parent | 2cc10b0704d7352198374597075ef184253026be (diff) | |
| download | srdwm-d2952af18b907a5b18fccd26468a74aabe49bb2f.tar.gz srdwm-d2952af18b907a5b18fccd26468a74aabe49bb2f.zip | |
Rounded corners on udev/Pixman backend, opt-in and off by default
CPU-side rounded corners for the software-only udev/Pixman renderer,
which has no shader stage to hook the existing GLES version into.
Reads a window's own committed wl_shm buffer, punches premultiplied-
alpha holes into the four corner regions, and hands the masked copy
to MemoryRenderBuffer - the same path already used for titlebar/
border/shadow bitmaps, so it composites through the ordinary unmasked
path and the corners genuinely disappear rather than being painted
over.
Cached per window, invalidated by a per-commit content_epoch counter
rather than rebuilt every frame, so an idle window costs nothing once
masked. general.rounded_corners now defaults per backend instead of
one global true: on for GLES/winit (a real GPU shader, no measurable
cost), off for udev/Pixman (an untested-on-real-hardware CPU cost for
constantly-repainting clients) - WindowManager.rounded_corners_enabled
is Option<bool> so the backend can tell "unset" from "explicitly off".
Diffstat (limited to 'crates/wayland/src/elements.rs')
| -rw-r--r-- | crates/wayland/src/elements.rs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/crates/wayland/src/elements.rs b/crates/wayland/src/elements.rs index c9f1d6c..c8cb10c 100644 --- a/crates/wayland/src/elements.rs +++ b/crates/wayland/src/elements.rs @@ -147,6 +147,47 @@ where render_elements_from_surface_tree(renderer, surface, location, 1.0, alpha, Kind::Unspecified) } +/// Looks up (rebuilding first if stale) the Pixman-backend rounded-corner +/// masked copy of `surface`'s content - see `rounded_corners_pixman`'s +/// module doc comment for what this actually does and why it needs a cache +/// at all. `epoch` is the window's current `CompState::content_epoch` +/// value (bumped once per real commit, in `commit()`); the cached entry is +/// only rebuilt when that no longer matches what it was last built from, so +/// a window that isn't currently repainting costs nothing here beyond one +/// `HashMap` lookup per frame. +/// +/// Free function taking the two fields it needs directly, rather than a +/// `CompState` method, so it can be called from inside `udev.rs`'s render +/// loop alongside the already-live `self.udev.as_mut()` borrow - see that +/// call site. +/// +/// `None` either because masking genuinely isn't possible right now (falls +/// through to `rounded_corners_pixman::masked_content_buffer`'s own `None` +/// cases) or because it hasn't been attempted yet this call; either way the +/// caller's fallback is the same: render `surface`'s content unrounded via +/// [`surface_content_elements`]. +pub(crate) fn rounded_content_buffer<'a>( + cache: &'a mut std::collections::HashMap<srdwm_core::WindowId, (u64, smithay::backend::renderer::element::memory::MemoryRenderBuffer)>, + epoch: u64, + id: srdwm_core::WindowId, + surface: &WlSurface, + radius: f32, + corners: crate::rounded_corners::RoundedCorners, +) -> Option<&'a smithay::backend::renderer::element::memory::MemoryRenderBuffer> { + let stale = cache.get(&id).map(|(built, _)| *built != epoch).unwrap_or(true); + if stale { + match crate::rounded_corners_pixman::masked_content_buffer(surface, radius, corners) { + Some(buf) => { + cache.insert(id, (epoch, buf)); + } + None => { + cache.remove(&id); + } + } + } + cache.get(&id).map(|(_, b)| b) +} + /// Every mapped layer-shell surface on `output` whose [`Layer`] `include` /// accepts, each rendered via [`surface_content_elements`] at full opacity /// - layer-shell surfaces (bars, docks, wallpaper engines) don't have a |