WayVR: Minor refactoring, fix panic after dropping an overlay

This commit is contained in:
Aleksander
2025-04-23 21:14:46 +02:00
parent 33354935f0
commit 71ad1f043f
4 changed files with 63 additions and 57 deletions

View File

@@ -60,6 +60,7 @@ pub struct Display {
pub layout: packet_server::WvrDisplayWindowLayout, pub layout: packet_server::WvrDisplayWindowLayout,
pub overlay_id: Option<OverlayID>, pub overlay_id: Option<OverlayID>,
pub wants_redraw: bool, pub wants_redraw: bool,
pub rendered_frame_count: u32,
pub primary: bool, pub primary: bool,
pub wm: Rc<RefCell<window::WindowManager>>, pub wm: Rc<RefCell<window::WindowManager>>,
pub displayed_windows: Vec<DisplayWindow>, pub displayed_windows: Vec<DisplayWindow>,
@@ -166,6 +167,7 @@ impl Display {
tasks: SyncEventQueue::new(), tasks: SyncEventQueue::new(),
visible: true, visible: true,
wants_redraw: true, wants_redraw: true,
rendered_frame_count: 0,
layout: packet_server::WvrDisplayWindowLayout::Tiling, layout: packet_server::WvrDisplayWindowLayout::Tiling,
}) })
} }
@@ -381,6 +383,8 @@ impl Display {
})); }));
} }
self.rendered_frame_count += 1;
Ok(()) Ok(())
} }

View File

@@ -74,9 +74,7 @@ pub enum WayVRTask {
NewToplevel(ClientId, ToplevelSurface), NewToplevel(ClientId, ToplevelSurface),
DropToplevel(ClientId, ToplevelSurface), DropToplevel(ClientId, ToplevelSurface),
NewExternalProcess(ExternalProcessRequest), NewExternalProcess(ExternalProcessRequest),
DropOverlay(super::overlay::OverlayID),
ProcessTerminationRequest(process::ProcessHandle), ProcessTerminationRequest(process::ProcessHandle),
Haptics(super::input::Haptics),
} }
#[derive(Clone)] #[derive(Clone)]
@@ -87,6 +85,8 @@ pub enum WayVRSignal {
packet_server::WvrDisplayWindowLayout, packet_server::WvrDisplayWindowLayout,
), ),
BroadcastStateChanged(packet_server::WvrStateChanged), BroadcastStateChanged(packet_server::WvrStateChanged),
DropOverlay(super::overlay::OverlayID),
Haptics(super::input::Haptics),
} }
pub enum BlitMethod { pub enum BlitMethod {
@@ -124,7 +124,6 @@ pub struct WayVRState {
pub tasks: SyncEventQueue<WayVRTask>, pub tasks: SyncEventQueue<WayVRTask>,
pub signals: SyncEventQueue<WayVRSignal>, pub signals: SyncEventQueue<WayVRSignal>,
ticks: u64, ticks: u64,
pub pending_haptic: Option<super::input::Haptics>,
cur_modifiers: u8, cur_modifiers: u8,
} }
@@ -145,7 +144,6 @@ pub enum TickTask {
packet_client::WvrDisplayCreateParams, packet_client::WvrDisplayCreateParams,
Option<display::DisplayHandle>, /* existing handle? */ Option<display::DisplayHandle>, /* existing handle? */
), ),
DropOverlay(super::overlay::OverlayID),
} }
impl WayVR { impl WayVR {
@@ -268,7 +266,6 @@ impl WayVR {
dashboard_display: None, dashboard_display: None,
ticks: 0, ticks: 0,
tasks, tasks,
pending_haptic: None,
signals: SyncEventQueue::new(), signals: SyncEventQueue::new(),
cur_modifiers: 0, cur_modifiers: 0,
}; };
@@ -276,15 +273,15 @@ impl WayVR {
Ok(Self { state, ipc_server }) Ok(Self { state, ipc_server })
} }
pub fn tick_display(&mut self, display: display::DisplayHandle) -> anyhow::Result<bool> { pub fn render_display(&mut self, display: display::DisplayHandle) -> anyhow::Result<bool> {
// millis since the start of wayvr
let display = self let display = self
.state .state
.displays .displays
.get_mut(&display) .get_mut(&display)
.ok_or_else(|| anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?; .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 // Nothing changed, do not render
return Ok(false); return Ok(false);
} }
@@ -294,6 +291,7 @@ impl WayVR {
return Ok(false); return Ok(false);
} }
// millis since the start of wayvr
let time_ms = get_millis() - self.state.time_start; let time_ms = get_millis() - self.state.time_start;
display.tick_render(&mut self.state.manager.state.gles_renderer, time_ms)?; display.tick_render(&mut self.state.manager.state.gles_renderer, time_ms)?;
@@ -362,9 +360,6 @@ impl WayVR {
WayVRTask::NewExternalProcess(req) => { WayVRTask::NewExternalProcess(req) => {
tasks.push(TickTask::NewExternalProcess(req)); tasks.push(TickTask::NewExternalProcess(req));
} }
WayVRTask::DropOverlay(overlay_id) => {
tasks.push(TickTask::DropOverlay(overlay_id));
}
WayVRTask::NewToplevel(client_id, toplevel) => { WayVRTask::NewToplevel(client_id, toplevel) => {
// Attach newly created toplevel surfaces to displays // Attach newly created toplevel surfaces to displays
for client in &self.state.manager.clients { for client in &self.state.manager.clients {
@@ -432,9 +427,6 @@ impl WayVR {
process.terminate(); 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 { if let Some(overlay_id) = display.overlay_id {
self.tasks.send(WayVRTask::DropOverlay(overlay_id)); self.signals.send(WayVRSignal::DropOverlay(overlay_id));
} else { } else {
log::warn!("Destroying display without OverlayID set"); // This shouldn't happen, but log it anyways. log::warn!("Destroying display without OverlayID set"); // This shouldn't happen, but log it anyways.
} }

View File

@@ -470,14 +470,13 @@ impl Connection {
params: &mut TickParams, params: &mut TickParams,
haptics_params: packet_client::WlxHapticsParams, haptics_params: packet_client::WlxHapticsParams,
) { ) {
params params.state.signals.send(super::WayVRSignal::Haptics(
.state crate::backend::input::Haptics {
.tasks
.send(super::WayVRTask::Haptics(crate::backend::input::Haptics {
duration: haptics_params.duration, duration: haptics_params.duration,
frequency: haptics_params.frequency, frequency: haptics_params.frequency,
intensity: haptics_params.intensity, intensity: haptics_params.intensity,
})); },
));
} }
fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> { fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> {

View File

@@ -59,6 +59,7 @@ pub struct WayVRData {
overlays_to_create: Vec<OverlayToCreate>, overlays_to_create: Vec<OverlayToCreate>,
dashboard_executed: bool, dashboard_executed: bool,
pub data: WayVR, pub data: WayVR,
pending_haptics: Option<input::Haptics>,
} }
impl WayVRData { impl WayVRData {
@@ -68,6 +69,7 @@ impl WayVRData {
data: WayVR::new(config)?, data: WayVR::new(config)?,
overlays_to_create: Vec::new(), overlays_to_create: Vec::new(),
dashboard_executed: false, dashboard_executed: false,
pending_haptics: None,
}) })
} }
@@ -115,18 +117,21 @@ impl InteractionHandler for WayVRInteractionHandler {
) -> Option<input::Haptics> { ) -> Option<input::Haptics> {
let ctx = self.context.borrow(); 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 pos = self.mouse_transform.transform_point2(hit.uv);
let x = ((pos.x * f32::from(disp.width)) as i32).max(0); 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 y = ((pos.y * f32::from(disp.height)) as i32).max(0);
let ctx = self.context.borrow(); 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) { fn on_left(&mut self, _app: &mut state::AppState, _pointer: usize) {
@@ -169,12 +174,17 @@ impl InteractionHandler for WayVRInteractionHandler {
} }
} }
struct ImageData {
vk_image: Arc<vulkano::image::Image>,
vk_image_view: Arc<vulkano::image::view::ImageView>,
}
pub struct WayVRRenderer { pub struct WayVRRenderer {
pipeline: Arc<WlxPipeline>, pipeline: Arc<WlxPipeline>,
vk_image: Option<Arc<vulkano::image::Image>>, image: Option<ImageData>,
vk_image_view: Option<Arc<vulkano::image::view::ImageView>>,
context: Rc<RefCell<WayVRContext>>, context: Rc<RefCell<WayVRContext>>,
graphics: Arc<WlxGraphics>, graphics: Arc<WlxGraphics>,
resolution: [u16; 2],
} }
impl WayVRRenderer { impl WayVRRenderer {
@@ -182,6 +192,7 @@ impl WayVRRenderer {
app: &state::AppState, app: &state::AppState,
wvr: Rc<RefCell<WayVRData>>, wvr: Rc<RefCell<WayVRData>>,
display: wayvr::display::DisplayHandle, display: wayvr::display::DisplayHandle,
resolution: [u16; 2],
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
let Ok(shaders) = app.graphics.shared_shaders.read() else { let Ok(shaders) = app.graphics.shared_shaders.read() else {
anyhow::bail!("Failed to lock shared shaders for reading"); anyhow::bail!("Failed to lock shared shaders for reading");
@@ -197,9 +208,9 @@ impl WayVRRenderer {
Ok(Self { Ok(Self {
pipeline, pipeline,
context: Rc::new(RefCell::new(WayVRContext::new(wvr, display))), context: Rc::new(RefCell::new(WayVRContext::new(wvr, display))),
vk_image: None,
vk_image_view: None,
graphics: app.graphics.clone(), graphics: app.graphics.clone(),
image: None,
resolution,
}) })
} }
} }
@@ -470,6 +481,13 @@ where
.ipc_server .ipc_server
.broadcast(packet_server::PacketServer::WvrStateChanged(packet)); .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()?; upload.build_and_execute_now()?;
//buffers.push(upload.build()?); //buffers.push(upload.build()?);
self.image = Some(ImageData {
self.vk_image = Some(tex.clone()); vk_image: tex.clone(),
self.vk_image_view = Some(ImageView::new_default(tex).unwrap()); vk_image_view: ImageView::new_default(tex).unwrap(),
});
Ok(()) Ok(())
} }
@@ -592,7 +606,7 @@ impl WayVRRenderer {
&mut self, &mut self,
data: &wayvr::egl_data::RenderDMAbufData, data: &wayvr::egl_data::RenderDMAbufData,
) -> anyhow::Result<()> { ) -> 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 return Ok(()); // already initialized and automatically updated due to direct zero-copy textue access
} }
@@ -640,8 +654,10 @@ impl WayVRRenderer {
&data.mod_info.modifiers, &data.mod_info.modifiers,
)?; )?;
self.vk_image = Some(tex.clone()); self.image = Some(ImageData {
self.vk_image_view = Some(vulkano::image::view::ImageView::new_default(tex).unwrap()); vk_image: tex.clone(),
vk_image_view: ImageView::new_default(tex).unwrap(),
});
Ok(()) Ok(())
} }
} }
@@ -668,10 +684,10 @@ impl OverlayRenderer for WayVRRenderer {
fn should_render(&mut self, _app: &mut AppState) -> anyhow::Result<ShouldRender> { fn should_render(&mut self, _app: &mut AppState) -> anyhow::Result<ShouldRender> {
let ctx = self.context.borrow(); let ctx = self.context.borrow();
let mut wayvr = ctx.wayvr.borrow_mut(); 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, Ok(r) => r,
Err(e) => { Err(e) => {
log::error!("tick_display failed: {e}"); log::error!("render_display failed: {e}");
return Ok(ShouldRender::Unable); 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); return Ok(false);
}; };
let set0 = let set0 = self.pipeline.uniform_sampler(
self.pipeline 0,
.uniform_sampler(0, view.clone(), app.graphics.texture_filtering)?; image.vk_image_view.clone(),
app.graphics.texture_filtering,
)?;
let set1 = self.pipeline.uniform_buffer(1, vec![alpha])?; let set1 = self.pipeline.uniform_buffer(1, vec![alpha])?;
@@ -740,17 +758,10 @@ impl OverlayRenderer for WayVRRenderer {
} }
fn frame_meta(&mut self) -> Option<FrameMeta> { fn frame_meta(&mut self) -> Option<FrameMeta> {
let ctx = self.context.borrow(); Some(FrameMeta {
let wayvr = ctx.wayvr.borrow_mut(); extent: [self.resolution[0] as u32, self.resolution[1] as u32, 1],
wayvr ..Default::default()
.data })
.state
.displays
.get(&ctx.display)
.map(|disp| FrameMeta {
extent: [disp.width as _, disp.height as _, 1],
..Default::default()
})
} }
} }
@@ -782,7 +793,7 @@ where
let wayvr = app.get_wayvr()?; 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 context = renderer.context.clone();
let backend = Box::new(SplitOverlayBackend { let backend = Box::new(SplitOverlayBackend {