From d2952af18b907a5b18fccd26468a74aabe49bb2f Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:43:00 +0200 Subject: 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 so the backend can tell "unset" from "explicitly off". --- crates/wayland/src/udev.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'crates/wayland/src/udev.rs') diff --git a/crates/wayland/src/udev.rs b/crates/wayland/src/udev.rs index 40c0ce5..cdea265 100644 --- a/crates/wayland/src/udev.rs +++ b/crates/wayland/src/udev.rs @@ -207,6 +207,10 @@ impl CompState { // looked up fresh per head (head-local `origin` translation). let ids: Vec = if locked { Vec::new() } else { self.wm.borrow().visible_windows_front_to_back().map(|w| w.id).collect() }; let focused = self.wm.borrow().focused_id(); + // Default `false` here, unlike winit's `unwrap_or(true)` - see + // `rounded_corners_pixman`'s module doc comment for the CPU cost + // that makes this backend opt-in rather than on by default. + let rounded_corners_enabled = self.wm.borrow().rounded_corners_enabled.unwrap_or(false); let popup_targets = if locked { Vec::new() } else { crate::elements::popup_targets(self) }; // Which heads are eligible, and what each needs, gathered before the @@ -458,7 +462,29 @@ impl CompState { if let Some(surface) = crate::elements::window_wl_surface(dwindow) { let band = if w.decorated { srdwm_core::TITLEBAR_HEIGHT as i32 } else { 0 }; let pos = (geom.x - origin.x, geom.y + band - origin.y); - custom_elements.extend(crate::elements::surface_content_elements(&mut udev.renderer, &surface, pos, w.opacity)); + let mut rounded_elem = None; + if rounded_corners_enabled { + let epoch = self.content_epoch.get(&id).copied().unwrap_or(0); + // Bottom-only for a decorated window, same + // reasoning as `winit.rs`'s identical split: + // the top two corners are already hidden + // under the titlebar band's own rounded + // bitmap. + let corners = if w.decorated { crate::rounded_corners::RoundedCorners::BOTTOM_ONLY } else { crate::rounded_corners::RoundedCorners::ALL }; + if let Some(buffer) = + crate::elements::rounded_content_buffer(&mut self.rounded_content_buffers, epoch, id, &surface, decoration::CORNER_RADIUS as f32, corners) + { + match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, (pos.0 as f64, pos.1 as f64), buffer, Some(w.opacity), None, None, Kind::Unspecified) + { + Ok(elem) => rounded_elem = Some(elem), + Err(e) => log::warn!("udev: failed to import rounded content buffer: {e}"), + } + } + } + match rounded_elem { + Some(elem) => custom_elements.push(crate::elements::OverlayElement::Memory(elem)), + None => custom_elements.extend(crate::elements::surface_content_elements(&mut udev.renderer, &surface, pos, w.opacity)), + } } } occluders.push(geom); @@ -1080,6 +1106,8 @@ impl UdevPlatform { border_top_decorations: HashMap::new(), shadow_buffers: HashMap::new(), rounded_corners_program: None, + content_epoch: HashMap::new(), + rounded_content_buffers: HashMap::new(), border_side_buffers: HashMap::new(), last_synced_size: HashMap::new(), pending: pending.clone(), -- cgit v1.2.3