diff --git a/wlx-overlay-s/src/backend/wayvr/comp.rs b/wlx-overlay-s/src/backend/wayvr/comp.rs index ea1eff3..fae704d 100644 --- a/wlx-overlay-s/src/backend/wayvr/comp.rs +++ b/wlx-overlay-s/src/backend/wayvr/comp.rs @@ -4,7 +4,7 @@ use smithay::input::{Seat, SeatHandler, SeatState}; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::reexports::wayland_server; use smithay::reexports::wayland_server::Resource; -use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_output, wl_seat, wl_surface}; +use smithay::reexports::wayland_server::protocol::{wl_buffer, wl_output, wl_seat}; use smithay::wayland::buffer::BufferHandler; use smithay::wayland::dmabuf::{ DmabufFeedback, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf, @@ -21,9 +21,7 @@ use std::os::fd::OwnedFd; use std::sync::{Arc, Mutex}; use smithay::utils::Serial; -use smithay::wayland::compositor::{ - self, BufferAssignment, SurfaceAttributes, TraversalAction, with_surface_tree_downward, -}; +use smithay::wayland::compositor::{self, BufferAssignment, SurfaceAttributes}; use smithay::wayland::selection::SelectionHandler; use smithay::wayland::selection::data_device::{ @@ -36,8 +34,8 @@ use wayland_server::Client; use wayland_server::backend::{ClientData, ClientId, DisconnectReason}; use wayland_server::protocol::wl_surface::WlSurface; -use crate::backend::wayvr::SurfaceBufWithImage; use crate::backend::wayvr::image_importer::ImageImporter; +use crate::backend::wayvr::{SurfaceBufWithImage, time}; use crate::ipc::event_queue::SyncEventQueue; use super::WayVRTask; @@ -83,66 +81,81 @@ impl compositor::CompositorHandler for Application { match attrs.buffer.take() { Some(BufferAssignment::NewBuffer(buffer)) => { - let current = SurfaceBufWithImage::get_from_surface(states); - - if current.is_none_or(|c| c.buffer != buffer) { - match buffer_type(&buffer) { - Some(BufferType::Dma) => { - let dmabuf = get_dmabuf(&buffer).unwrap(); // always Ok due to buffer_type - if let Ok(image) = - self.image_importer.get_or_import_dmabuf(dmabuf.clone()) + match buffer_type(&buffer) { + Some(BufferType::Dma) => { + let dmabuf = get_dmabuf(&buffer).unwrap(); // always Ok due to buffer_type + if let Ok(image) = self + .image_importer + .get_or_import_dmabuf(dmabuf.clone()) + .inspect_err(|e| { + log::warn!("wayland_server failed to import DMA-buf: {e:?}") + }) + { + let sbwi = SurfaceBufWithImage { + image, + transform: wl_transform_to_frame_transform( + attrs.buffer_transform, + ), + scale: attrs.buffer_scale, + dmabuf: true, + }; + sbwi.apply_to_surface(states); + } + } + Some(BufferType::Shm) => { + let _ = with_buffer_contents(&buffer, |data, size, buf| { + if let Ok(image) = self + .image_importer + .import_shm(data, size, buf) + .inspect_err(|e| { + log::warn!("wayland_server failed to import SHM: {e:?}") + }) { let sbwi = SurfaceBufWithImage { image, - buffer, transform: wl_transform_to_frame_transform( attrs.buffer_transform, ), scale: attrs.buffer_scale, + dmabuf: false, }; sbwi.apply_to_surface(states); } - } - Some(BufferType::Shm) => { - let _ = with_buffer_contents(&buffer, |data, size, buf| { - if let Ok(image) = - self.image_importer.import_shm(data, size, buf) - { - let sbwi = SurfaceBufWithImage { - image, - buffer: buffer.clone(), - transform: wl_transform_to_frame_transform( - attrs.buffer_transform, - ), - scale: attrs.buffer_scale, - }; - sbwi.apply_to_surface(states); - } - }); - } - Some(BufferType::SinglePixel) => { - let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok - if let Ok(image) = self.image_importer.import_spb(spb) { - let sbwi = SurfaceBufWithImage { - image, - buffer, - transform: wl_transform_to_frame_transform( - // does this even matter - attrs.buffer_transform, - ), - scale: attrs.buffer_scale, - }; - sbwi.apply_to_surface(states); - } - } - Some(other) => log::warn!("Unsupported wl_buffer format: {other:?}"), - None => { /* don't draw anything */ } + }); } + Some(BufferType::SinglePixel) => { + let spb = get_single_pixel_buffer(&buffer).unwrap(); // always Ok + if let Ok(image) = + self.image_importer.import_spb(spb).inspect_err(|e| { + log::warn!("wayland_server failed to import SPB: {e:?}") + }) + { + let sbwi = SurfaceBufWithImage { + image, + transform: wl_transform_to_frame_transform( + // does this even matter + attrs.buffer_transform, + ), + scale: attrs.buffer_scale, + dmabuf: false, + }; + sbwi.apply_to_surface(states); + } + } + Some(other) => log::warn!("Unsupported wl_buffer format: {other:?}"), + None => { /* don't draw anything */ } } + buffer.release(); } Some(BufferAssignment::Removed) => {} None => {} } + + let t = time::get_millis() as u32; + let callbacks = std::mem::take(&mut attrs.frame_callbacks); + for cb in callbacks { + cb.done(t); + } }); self.redraw_requests.insert(surface.id()); @@ -286,28 +299,6 @@ delegate_seat!(Application); delegate_data_device!(Application); delegate_output!(Application); -pub fn send_frames_surface_tree(surface: &wl_surface::WlSurface, time: u32) { - with_surface_tree_downward( - surface, - (), - |_, _, &()| TraversalAction::DoChildren(()), - |_surf, states, &()| { - // the surface may not have any user_data if it is a subsurface and has not - // yet been committed - for callback in states - .cached_state - .get::() - .current() - .frame_callbacks - .drain(..) - { - callback.done(time); - } - }, - |_, _, &()| true, - ); -} - fn wl_transform_to_frame_transform( transform: wl_output::Transform, ) -> wlx_capture::frame::Transform { diff --git a/wlx-overlay-s/src/backend/wayvr/mod.rs b/wlx-overlay-s/src/backend/wayvr/mod.rs index 19195ec..9661870 100644 --- a/wlx-overlay-s/src/backend/wayvr/mod.rs +++ b/wlx-overlay-s/src/backend/wayvr/mod.rs @@ -14,7 +14,7 @@ use smallvec::SmallVec; use smithay::{ input::{SeatState, keyboard::XkbConfig}, output::{Mode, Output}, - reexports::wayland_server::{self, backend::ClientId, protocol::wl_buffer}, + reexports::wayland_server::{self, backend::ClientId}, wayland::{ compositor::{self, SurfaceData, with_states}, dmabuf::{DmabufFeedbackBuilder, DmabufState}, @@ -26,8 +26,6 @@ use smithay::{ use std::{ cell::RefCell, collections::{HashMap, HashSet}, - mem::MaybeUninit, - rc::Rc, sync::Arc, time::{Duration, Instant}, }; @@ -112,7 +110,7 @@ pub struct Config { pub struct WayVRState { time_start: u64, pub manager: client::WayVRCompositor, - pub wm: Rc>, + pub wm: window::WindowManager, pub processes: process::ProcessVec, pub config: Config, pub tasks: SyncEventQueue, @@ -241,7 +239,7 @@ impl WayVR { time_start, manager: client::WayVRCompositor::new(state, display, seat_keyboard, seat_pointer)?, processes: ProcessVec::new(), - wm: Rc::new(RefCell::new(window::WindowManager::new())), + wm: window::WindowManager::new(), config, ticks: 0, tasks, @@ -307,11 +305,7 @@ impl WayVR { continue; }; - let window_handle = self - .state - .wm - .borrow_mut() - .create_window(&toplevel, process_handle); + let window_handle = self.state.wm.create_window(&toplevel, process_handle); let title: Arc = with_states(toplevel.wl_surface(), |states| { states @@ -353,8 +347,8 @@ impl WayVR { continue; } - let mut wm = self.state.wm.borrow_mut(); - let Some(window_handle) = wm.find_window_handle(&toplevel) else { + let Some(window_handle) = self.state.wm.find_window_handle(&toplevel) + else { log::warn!("DropToplevel: Couldn't find matching window handle"); continue; }; @@ -365,9 +359,7 @@ impl WayVR { ))); } - wm.remove_window(window_handle); - - drop(wm); + self.state.wm.remove_window(window_handle); } } WayVRTask::ProcessTerminationRequest(process_handle) => { @@ -404,7 +396,7 @@ impl WayVRState { if self.mouse_freeze > Instant::now() { return; } - if let Some(window) = self.wm.borrow_mut().windows.get_mut(&handle) { + if let Some(window) = self.wm.windows.get_mut(&handle) { window.send_mouse_move(&mut self.manager, x, y); } } @@ -413,7 +405,7 @@ impl WayVRState { self.mouse_freeze = Instant::now() + Duration::from_millis(self.config.click_freeze_time_ms as _); - if let Some(window) = self.wm.borrow_mut().windows.get_mut(&handle) { + if let Some(window) = self.wm.windows.get_mut(&handle) { window.send_mouse_down(&mut self.manager, index); } } @@ -563,10 +555,10 @@ struct SurfaceBufWithImageContainer { #[derive(Clone)] pub struct SurfaceBufWithImage { - buffer: wl_buffer::WlBuffer, pub image: Arc, pub transform: Transform, pub scale: i32, + pub dmabuf: bool, } impl SurfaceBufWithImage { @@ -575,7 +567,11 @@ impl SurfaceBufWithImage { if let Some(container) = surface_data.data_map.get::() { container.inner.replace(self); } else { - surface_data.data_map.insert_if_missing(|| self); + surface_data + .data_map + .insert_if_missing(|| SurfaceBufWithImageContainer { + inner: RefCell::new(self), + }); } } diff --git a/wlx-overlay-s/src/ipc/ipc_server.rs b/wlx-overlay-s/src/ipc/ipc_server.rs index 3532d28..640b1db 100644 --- a/wlx-overlay-s/src/ipc/ipc_server.rs +++ b/wlx-overlay-s/src/ipc/ipc_server.rs @@ -199,7 +199,6 @@ impl Connection { list: params .wayland_state .wm - .borrow_mut() .windows .iter() .map(|(handle, win)| packet_server::WvrWindow { @@ -222,7 +221,6 @@ impl Connection { if let Some(window) = params .wayland_state .wm - .borrow_mut() .windows .get_mut(&wayvr::window::WindowHandle::from_packet(handle)) { diff --git a/wlx-overlay-s/src/overlays/wayvr.rs b/wlx-overlay-s/src/overlays/wayvr.rs index 16d0b36..bf7985b 100644 --- a/wlx-overlay-s/src/overlays/wayvr.rs +++ b/wlx-overlay-s/src/overlays/wayvr.rs @@ -12,7 +12,7 @@ use crate::{ backend::{ XrBackend, input::{self, HoverResult}, - wayvr::{self, SurfaceBufWithImage, WayVR, window::WindowManager}, + wayvr::{self, SurfaceBufWithImage, WayVR}, }, graphics::{ExtentExt, WGfxExtras}, ipc::{event_queue::SyncEventQueue, signal::WayVRSignal}, @@ -84,7 +84,6 @@ pub struct WayVRBackend { interaction_transform: Option, window: wayvr::window::WindowHandle, wayvr: Rc>, - wm: Rc>, just_resumed: bool, meta: Option, stereo: Option, @@ -98,12 +97,10 @@ impl WayVRBackend { wayvr: Rc>, window: wayvr::window::WindowHandle, ) -> anyhow::Result { - let wm = wayvr.borrow().data.state.wm.clone(); Ok(Self { name, pipeline: None, wayvr, - wm, window, mouse_transform: Affine2::IDENTITY, interaction_transform: None, @@ -134,8 +131,8 @@ impl OverlayBackend for WayVRBackend { } fn should_render(&mut self, app: &mut AppState) -> anyhow::Result { - let wm = self.wm.borrow(); - let Some(window) = wm.windows.get(&self.window) else { + let wayvr = &self.wayvr.borrow().data; + let Some(window) = wayvr.state.wm.windows.get(&self.window) else { log::debug!( "{:?}: WayVR overlay without matching window entry", self.name @@ -175,12 +172,19 @@ impl OverlayBackend for WayVRBackend { .as_ref() .is_none_or(|i| *i.image() != *surf.image.image()) { + log::trace!( + "{}: new {} image", + self.name, + surf.dmabuf.then_some("DMA-buf").unwrap_or("SHM") + ); self.cur_image = Some(surf.image); Ok(ShouldRender::Should) } else { + log::trace!("{}: no new image", self.name); Ok(ShouldRender::Can) } } else { + log::trace!("{}: no buffer for wl_surface", self.name); Ok(ShouldRender::Unable) } }) @@ -215,12 +219,13 @@ impl OverlayBackend for WayVRBackend { } fn on_hover(&mut self, _app: &mut state::AppState, hit: &input::PointerHit) -> HoverResult { - if let Some(window) = self.wm.borrow().windows.get(&self.window) { + let wayvr = &mut self.wayvr.borrow_mut().data; + if let Some((x, y)) = wayvr.state.wm.windows.get(&self.window).map(|window| { let pos = self.mouse_transform.transform_point2(hit.uv); let x = ((pos.x * (window.size_x as f32)) as u32).max(0); let y = ((pos.y * (window.size_y as f32)) as u32).max(0); - - let wayvr = &mut self.wayvr.borrow_mut().data; + (x, y) + }) { wayvr.state.send_mouse_move(self.window, x, y); }