fix(wayland): lock on commit

This commit is contained in:
Nova
2024-07-26 17:42:58 -04:00
parent 78912c8f1b
commit 48f15e848d
3 changed files with 123 additions and 69 deletions

View File

@@ -1,6 +1,5 @@
use crate::wayland::surface::CoreSurface;
use super::state::{ClientState, WaylandState}; use super::state::{ClientState, WaylandState};
use crate::wayland::surface::CoreSurface;
use portable_atomic::{AtomicU32, Ordering}; use portable_atomic::{AtomicU32, Ordering};
use smithay::{ use smithay::{
backend::renderer::utils::on_commit_buffer_handler, backend::renderer::utils::on_commit_buffer_handler,
@@ -38,6 +37,34 @@ impl CompositorHandler for WaylandState {
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState { fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
&client.get_data::<ClientState>().unwrap().compositor_state &client.get_data::<ClientState>().unwrap().compositor_state
} }
// fn new_subsurface(&mut self, surface: &WlSurface, parent: &WlSurface) {
// let Some(panel_item) = surface_panel_item(parent) else {
// return;
// };
// let uid = surface.insert_data(Arc::downgrade(&panel_item));
// }
// fn destroyed(&mut self, surface: &WlSurface) {
// let Some(panel_item) = surface_panel_item(surface) else {
// return;
// };
// let Some((id, _)) = panel_item
// .backend
// .subsurfaces
// .lock()
// .iter()
// .find(|(_, d)| *d == surface)
// else {
// return;
// };
// panel_item.backend.drop_subsurface(*id);
// // self..lock().insert(id, (popup, positioner));
// let child_data = self.child_data(id).unwrap();
// panel_item.create_child(id, &child_data);
// }
} }
delegate_compositor!(WaylandState); delegate_compositor!(WaylandState);

View File

@@ -22,7 +22,6 @@ use smithay::{
desktop::utils::send_frames_surface_tree, desktop::utils::send_frames_surface_tree,
output::Output, output::Output,
reexports::wayland_server::{self, protocol::wl_surface::WlSurface, Resource}, reexports::wayland_server::{self, protocol::wl_surface::WlSurface, Resource},
wayland::compositor::{self, SurfaceData},
}; };
use std::{ffi::c_void, sync::Arc, time::Duration}; use std::{ffi::c_void, sync::Arc, time::Duration};
use stereokit_rust::{ use stereokit_rust::{
@@ -99,70 +98,77 @@ impl CoreSurface {
return; return;
} }
let mapped = compositor::with_states(&wl_surface, |data| { self.update_textures(renderer);
data.data_map self.apply_surface_materials();
.get::<RendererSurfaceStateUserData>() }
.map(|surface_states| surface_states.lock().unwrap().buffer().is_some())
.unwrap_or(false) pub fn update_textures(&self, renderer: &mut GlesRenderer) {
}); let Some(wl_surface) = self.wl_surface() else {
return;
};
let mapped = wl_surface
.get_data_raw::<RendererSurfaceStateUserData, _, _>(|surface_states| {
surface_states.lock().unwrap().buffer().is_some()
})
.unwrap_or(false);
if !mapped { if !mapped {
return; return;
} }
let mut mapped_data = self.mapped_data.lock(); let mut mapped_data = self.mapped_data.lock();
self.with_states(|data| {
let Some(renderer_surface_state) = data
.data_map
.get::<RendererSurfaceStateUserData>()
.map(std::sync::Mutex::lock)
.and_then(Result::ok)
else {
return;
};
let Some(smithay_tex) = renderer_surface_state
.texture::<GlesRenderer>(renderer.id())
.cloned()
else {
return;
};
let Some(sk_tex) = self.sk_tex.get() else { let Some(smithay_tex) = wl_surface
return; .get_data_raw::<RendererSurfaceStateUserData, _, _>(|surface_states| {
}; surface_states
let Some(sk_mat) = self.sk_mat.get() else { .lock()
return; .unwrap()
}; .texture::<GlesRenderer>(renderer.id())
sk_tex .cloned()
.lock() })
.0 .flatten()
.set_native_surface( else {
smithay_tex.tex_id() as usize as *mut c_void, return;
TexType::ImageNomips, };
smithay::backend::renderer::gles::ffi::RGBA8.into(),
smithay_tex.width() as i32,
smithay_tex.height() as i32,
1,
false,
)
.sample_mode(TexSample::Point)
.address_mode(TexAddress::Clamp);
if let Some(material_offset) = self.material_offset.lock().delta() { let Some(sk_tex) = self.sk_tex.get() else {
sk_mat.lock().0.queue_offset(*material_offset as i32); return;
} };
let Some(sk_mat) = self.sk_mat.get() else {
return;
};
sk_tex
.lock()
.0
.set_native_surface(
smithay_tex.tex_id() as usize as *mut c_void,
TexType::ImageNomips,
smithay::backend::renderer::gles::ffi::RGBA8.into(),
smithay_tex.width() as i32,
smithay_tex.height() as i32,
1,
false,
)
.sample_mode(TexSample::Point)
.address_mode(TexAddress::Clamp);
let Some(surface_size) = renderer_surface_state.surface_size() else { if let Some(material_offset) = self.material_offset.lock().delta() {
return; sk_mat.lock().0.queue_offset(*material_offset as i32);
}; }
let new_mapped_data = CoreSurfaceData {
size: Vector2::from([surface_size.w as u32, surface_size.h as u32]), let Some(surface_size) = wl_surface
wl_tex: Some(SendWrapper::new(smithay_tex)), .get_data_raw::<RendererSurfaceStateUserData, _, _>(|surface_states| {
}; surface_states.lock().unwrap().surface_size()
*mapped_data = Some(new_mapped_data); })
}); .flatten()
drop(mapped_data); else {
self.apply_surface_materials(); return;
};
let new_mapped_data = CoreSurfaceData {
size: Vector2::from([surface_size.w as u32, surface_size.h as u32]),
wl_tex: Some(SendWrapper::new(smithay_tex)),
};
*mapped_data = Some(new_mapped_data);
} }
pub fn frame(&self, output: Output) { pub fn frame(&self, output: Output) {
@@ -201,11 +207,6 @@ impl CoreSurface {
self.weak_surface.upgrade().ok() self.weak_surface.upgrade().ok()
} }
pub fn with_states<T, F: FnOnce(&SurfaceData) -> T>(&self, f: F) -> Option<T> {
self.wl_surface()
.map(|wl_surface| compositor::with_states(&wl_surface, f))
}
pub fn size(&self) -> Option<Vector2<u32>> { pub fn size(&self) -> Option<Vector2<u32>> {
self.mapped_data.lock().as_ref().map(|d| d.size) self.mapped_data.lock().as_ref().map(|d| d.size)
} }

View File

@@ -16,6 +16,7 @@ use parking_lot::Mutex;
use rand::Rng; use rand::Rng;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smithay::{ use smithay::{
backend::renderer::utils::RendererSurfaceStateUserData,
delegate_xdg_shell, delegate_xdg_shell,
reexports::{ reexports::{
wayland_protocols::xdg::{ wayland_protocols::xdg::{
@@ -48,7 +49,7 @@ impl From<Rectangle<i32, Logical>> for Geometry {
} }
} }
fn surface_panel_item(wl_surface: &WlSurface) -> Option<Arc<PanelItem<XdgBackend>>> { pub fn surface_panel_item(wl_surface: &WlSurface) -> Option<Arc<PanelItem<XdgBackend>>> {
let panel_item = wl_surface let panel_item = wl_surface
.get_data::<Weak<PanelItem<XdgBackend>>>() .get_data::<Weak<PanelItem<XdgBackend>>>()
.as_ref() .as_ref()
@@ -119,14 +120,18 @@ impl XdgShellHandler for WaylandState {
let Some(panel_item) = surface_panel_item(surf) else { let Some(panel_item) = surface_panel_item(surf) else {
return; return;
}; };
let Some(core_surface) = CoreSurface::from_wl_surface(surf) else { let Some(size) = surf
.get_data_raw::<RendererSurfaceStateUserData, _, _>(|surface_states| {
surface_states.lock().unwrap().surface_size()
})
.flatten()
else {
return; return;
}; };
let size = [size.w as u32, size.h as u32].into();
surf.get_data_raw::<Mutex<Vector2<u32>>, _, _>(|old_size| { surf.get_data_raw::<Mutex<Vector2<u32>>, _, _>(|old_size| {
let mut old_size = old_size.lock(); let mut old_size = old_size.lock();
let Some(size) = core_surface.size() else {
return;
};
if *old_size != size { if *old_size != size {
panel_item.toplevel_size_changed(size); panel_item.toplevel_size_changed(size);
*old_size = size; *old_size = size;
@@ -295,13 +300,15 @@ delegate_xdg_shell!(WaylandState);
pub struct XdgBackend { pub struct XdgBackend {
toplevel: Mutex<Option<ToplevelSurface>>, toplevel: Mutex<Option<ToplevelSurface>>,
pub subsurfaces: Mutex<FxHashMap<u64, WlSurface>>,
popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>, popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
pub seat: Arc<SeatWrapper>, seat: Arc<SeatWrapper>,
} }
impl XdgBackend { impl XdgBackend {
pub fn create(toplevel: ToplevelSurface, seat: Arc<SeatWrapper>) -> Self { pub fn create(toplevel: ToplevelSurface, seat: Arc<SeatWrapper>) -> Self {
XdgBackend { XdgBackend {
toplevel: Mutex::new(Some(toplevel)), toplevel: Mutex::new(Some(toplevel)),
subsurfaces: Mutex::new(FxHashMap::default()),
popups: Mutex::new(FxHashMap::default()), popups: Mutex::new(FxHashMap::default()),
seat, seat,
} }
@@ -319,6 +326,24 @@ impl XdgBackend {
surface_panel_item(self.toplevel.lock().clone()?.wl_surface()) surface_panel_item(self.toplevel.lock().clone()?.wl_surface())
} }
pub fn new_subsurface(&self, id: u64, surface: WlSurface) {
let Some(panel_item) = self.panel_item() else {
return;
};
self.subsurfaces.lock().insert(id, surface);
let child_data = self.child_data(id).unwrap();
panel_item.create_child(id, &child_data);
}
pub fn drop_subsurface(&self, id: u64) {
let Some(panel_item) = self.panel_item() else {
return;
};
panel_item.destroy_child(id);
self.subsurfaces.lock().remove(&id);
}
pub fn new_popup(&self, id: u64, popup: PopupSurface, positioner: PositionerState) { pub fn new_popup(&self, id: u64, popup: PopupSurface, positioner: PositionerState) {
let Some(panel_item) = self.panel_item() else { let Some(panel_item) = self.panel_item() else {
return; return;
@@ -347,6 +372,7 @@ impl XdgBackend {
return; return;
}; };
panel_item.destroy_child(id); panel_item.destroy_child(id);
self.popups.lock().remove(&id);
} }
fn child_data(&self, id: u64) -> Option<ChildInfo> { fn child_data(&self, id: u64) -> Option<ChildInfo> {