diff --git a/src/backend/wayvr/display.rs b/src/backend/wayvr/display.rs index 7cbbb6d..1210c1b 100644 --- a/src/backend/wayvr/display.rs +++ b/src/backend/wayvr/display.rs @@ -60,6 +60,7 @@ pub struct Display { pub layout: packet_server::WvrDisplayWindowLayout, pub overlay_id: Option, pub wants_redraw: bool, + pub rendered_frame_count: u32, pub primary: bool, pub wm: Rc>, pub displayed_windows: Vec, @@ -166,6 +167,7 @@ impl Display { tasks: SyncEventQueue::new(), visible: true, wants_redraw: true, + rendered_frame_count: 0, layout: packet_server::WvrDisplayWindowLayout::Tiling, }) } @@ -381,6 +383,8 @@ impl Display { })); } + self.rendered_frame_count += 1; + Ok(()) } diff --git a/src/backend/wayvr/mod.rs b/src/backend/wayvr/mod.rs index e444709..0204322 100644 --- a/src/backend/wayvr/mod.rs +++ b/src/backend/wayvr/mod.rs @@ -74,9 +74,7 @@ pub enum WayVRTask { NewToplevel(ClientId, ToplevelSurface), DropToplevel(ClientId, ToplevelSurface), NewExternalProcess(ExternalProcessRequest), - DropOverlay(super::overlay::OverlayID), ProcessTerminationRequest(process::ProcessHandle), - Haptics(super::input::Haptics), } #[derive(Clone)] @@ -87,6 +85,8 @@ pub enum WayVRSignal { packet_server::WvrDisplayWindowLayout, ), BroadcastStateChanged(packet_server::WvrStateChanged), + DropOverlay(super::overlay::OverlayID), + Haptics(super::input::Haptics), } pub enum BlitMethod { @@ -124,7 +124,6 @@ pub struct WayVRState { pub tasks: SyncEventQueue, pub signals: SyncEventQueue, ticks: u64, - pub pending_haptic: Option, cur_modifiers: u8, } @@ -145,7 +144,6 @@ pub enum TickTask { packet_client::WvrDisplayCreateParams, Option, /* existing handle? */ ), - DropOverlay(super::overlay::OverlayID), } impl WayVR { @@ -268,7 +266,6 @@ impl WayVR { dashboard_display: None, ticks: 0, tasks, - pending_haptic: None, signals: SyncEventQueue::new(), cur_modifiers: 0, }; @@ -276,15 +273,15 @@ impl WayVR { Ok(Self { state, ipc_server }) } - pub fn tick_display(&mut self, display: display::DisplayHandle) -> anyhow::Result { - // millis since the start of wayvr + pub fn render_display(&mut self, display: display::DisplayHandle) -> anyhow::Result { let display = self .state .displays .get_mut(&display) .ok_or_else(|| anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?; - if !display.wants_redraw { + /* Buffer warm-up is required, always two first calls of this function are always rendered */ + if !display.wants_redraw && display.rendered_frame_count >= 2 { // Nothing changed, do not render return Ok(false); } @@ -294,6 +291,7 @@ impl WayVR { return Ok(false); } + // millis since the start of wayvr let time_ms = get_millis() - self.state.time_start; display.tick_render(&mut self.state.manager.state.gles_renderer, time_ms)?; @@ -362,9 +360,6 @@ impl WayVR { WayVRTask::NewExternalProcess(req) => { tasks.push(TickTask::NewExternalProcess(req)); } - WayVRTask::DropOverlay(overlay_id) => { - tasks.push(TickTask::DropOverlay(overlay_id)); - } WayVRTask::NewToplevel(client_id, toplevel) => { // Attach newly created toplevel surfaces to displays for client in &self.state.manager.clients { @@ -432,9 +427,6 @@ impl WayVR { process.terminate(); } } - WayVRTask::Haptics(haptics) => { - self.state.pending_haptic = Some(haptics); - } } } @@ -592,7 +584,7 @@ impl WayVRState { }; if let Some(overlay_id) = display.overlay_id { - self.tasks.send(WayVRTask::DropOverlay(overlay_id)); + self.signals.send(WayVRSignal::DropOverlay(overlay_id)); } else { log::warn!("Destroying display without OverlayID set"); // This shouldn't happen, but log it anyways. } diff --git a/src/backend/wayvr/server_ipc.rs b/src/backend/wayvr/server_ipc.rs index 0eebbc5..6545898 100644 --- a/src/backend/wayvr/server_ipc.rs +++ b/src/backend/wayvr/server_ipc.rs @@ -470,14 +470,13 @@ impl Connection { params: &mut TickParams, haptics_params: packet_client::WlxHapticsParams, ) { - params - .state - .tasks - .send(super::WayVRTask::Haptics(crate::backend::input::Haptics { + params.state.signals.send(super::WayVRSignal::Haptics( + crate::backend::input::Haptics { duration: haptics_params.duration, frequency: haptics_params.frequency, intensity: haptics_params.intensity, - })); + }, + )); } fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> { diff --git a/src/overlays/wayvr.rs b/src/overlays/wayvr.rs index 8ab5aa0..a89756a 100644 --- a/src/overlays/wayvr.rs +++ b/src/overlays/wayvr.rs @@ -59,6 +59,7 @@ pub struct WayVRData { overlays_to_create: Vec, dashboard_executed: bool, pub data: WayVR, + pending_haptics: Option, } impl WayVRData { @@ -68,6 +69,7 @@ impl WayVRData { data: WayVR::new(config)?, overlays_to_create: Vec::new(), dashboard_executed: false, + pending_haptics: None, }) } @@ -115,18 +117,21 @@ impl InteractionHandler for WayVRInteractionHandler { ) -> Option { let ctx = self.context.borrow(); - let wayvr = &mut ctx.wayvr.borrow_mut().data; + let wayvr = &mut ctx.wayvr.borrow_mut(); - if let Some(disp) = wayvr.state.displays.get(&ctx.display) { + if let Some(disp) = wayvr.data.state.displays.get(&ctx.display) { let pos = self.mouse_transform.transform_point2(hit.uv); let x = ((pos.x * f32::from(disp.width)) as i32).max(0); let y = ((pos.y * f32::from(disp.height)) as i32).max(0); let ctx = self.context.borrow(); - wayvr.state.send_mouse_move(ctx.display, x as u32, y as u32); + wayvr + .data + .state + .send_mouse_move(ctx.display, x as u32, y as u32); } - wayvr.state.pending_haptic.take() + wayvr.pending_haptics.take() } fn on_left(&mut self, _app: &mut state::AppState, _pointer: usize) { @@ -169,12 +174,17 @@ impl InteractionHandler for WayVRInteractionHandler { } } +struct ImageData { + vk_image: Arc, + vk_image_view: Arc, +} + pub struct WayVRRenderer { pipeline: Arc, - vk_image: Option>, - vk_image_view: Option>, + image: Option, context: Rc>, graphics: Arc, + resolution: [u16; 2], } impl WayVRRenderer { @@ -182,6 +192,7 @@ impl WayVRRenderer { app: &state::AppState, wvr: Rc>, display: wayvr::display::DisplayHandle, + resolution: [u16; 2], ) -> anyhow::Result { let Ok(shaders) = app.graphics.shared_shaders.read() else { anyhow::bail!("Failed to lock shared shaders for reading"); @@ -197,9 +208,9 @@ impl WayVRRenderer { Ok(Self { pipeline, context: Rc::new(RefCell::new(WayVRContext::new(wvr, display))), - vk_image: None, - vk_image_view: None, graphics: app.graphics.clone(), + image: None, + resolution, }) } } @@ -470,6 +481,13 @@ where .ipc_server .broadcast(packet_server::PacketServer::WvrStateChanged(packet)); } + wayvr::WayVRSignal::DropOverlay(overlay_id) => { + app.tasks + .enqueue(TaskType::DropOverlay(OverlaySelector::Id(overlay_id))); + } + wayvr::WayVRSignal::Haptics(haptics) => { + wayvr.pending_haptics = Some(haptics); + } } } @@ -547,10 +565,6 @@ where }, }); } - wayvr::TickTask::DropOverlay(overlay_id) => { - app.tasks - .enqueue(TaskType::DropOverlay(OverlaySelector::Id(overlay_id))); - } } } @@ -581,10 +595,10 @@ impl WayVRRenderer { upload.build_and_execute_now()?; //buffers.push(upload.build()?); - - self.vk_image = Some(tex.clone()); - self.vk_image_view = Some(ImageView::new_default(tex).unwrap()); - + self.image = Some(ImageData { + vk_image: tex.clone(), + vk_image_view: ImageView::new_default(tex).unwrap(), + }); Ok(()) } @@ -592,7 +606,7 @@ impl WayVRRenderer { &mut self, data: &wayvr::egl_data::RenderDMAbufData, ) -> anyhow::Result<()> { - if self.vk_image.is_some() { + if self.image.is_some() { return Ok(()); // already initialized and automatically updated due to direct zero-copy textue access } @@ -640,8 +654,10 @@ impl WayVRRenderer { &data.mod_info.modifiers, )?; - self.vk_image = Some(tex.clone()); - self.vk_image_view = Some(vulkano::image::view::ImageView::new_default(tex).unwrap()); + self.image = Some(ImageData { + vk_image: tex.clone(), + vk_image_view: ImageView::new_default(tex).unwrap(), + }); Ok(()) } } @@ -668,10 +684,10 @@ impl OverlayRenderer for WayVRRenderer { fn should_render(&mut self, _app: &mut AppState) -> anyhow::Result { let ctx = self.context.borrow(); let mut wayvr = ctx.wayvr.borrow_mut(); - let redrawn = match wayvr.data.tick_display(ctx.display) { + let redrawn = match wayvr.data.render_display(ctx.display) { Ok(r) => r, Err(e) => { - log::error!("tick_display failed: {e}"); + log::error!("render_display failed: {e}"); return Ok(ShouldRender::Unable); } }; @@ -714,13 +730,15 @@ impl OverlayRenderer for WayVRRenderer { } } - let Some(view) = self.vk_image_view.as_ref() else { + let Some(image) = self.image.as_ref() else { return Ok(false); }; - let set0 = - self.pipeline - .uniform_sampler(0, view.clone(), app.graphics.texture_filtering)?; + let set0 = self.pipeline.uniform_sampler( + 0, + image.vk_image_view.clone(), + app.graphics.texture_filtering, + )?; let set1 = self.pipeline.uniform_buffer(1, vec![alpha])?; @@ -740,17 +758,10 @@ impl OverlayRenderer for WayVRRenderer { } fn frame_meta(&mut self) -> Option { - let ctx = self.context.borrow(); - let wayvr = ctx.wayvr.borrow_mut(); - wayvr - .data - .state - .displays - .get(&ctx.display) - .map(|disp| FrameMeta { - extent: [disp.width as _, disp.height as _, 1], - ..Default::default() - }) + Some(FrameMeta { + extent: [self.resolution[0] as u32, self.resolution[1] as u32, 1], + ..Default::default() + }) } } @@ -782,7 +793,7 @@ where let wayvr = app.get_wayvr()?; - let renderer = WayVRRenderer::new(app, wayvr, display_handle)?; + let renderer = WayVRRenderer::new(app, wayvr, display_handle, [display_width, display_height])?; let context = renderer.context.clone(); let backend = Box::new(SplitOverlayBackend {