fix(wayland): lock on commit
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use crate::wayland::surface::CoreSurface;
|
||||
|
||||
use super::state::{ClientState, WaylandState};
|
||||
use crate::wayland::surface::CoreSurface;
|
||||
use portable_atomic::{AtomicU32, Ordering};
|
||||
use smithay::{
|
||||
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 {
|
||||
&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);
|
||||
|
||||
@@ -22,7 +22,6 @@ use smithay::{
|
||||
desktop::utils::send_frames_surface_tree,
|
||||
output::Output,
|
||||
reexports::wayland_server::{self, protocol::wl_surface::WlSurface, Resource},
|
||||
wayland::compositor::{self, SurfaceData},
|
||||
};
|
||||
use std::{ffi::c_void, sync::Arc, time::Duration};
|
||||
use stereokit_rust::{
|
||||
@@ -99,70 +98,77 @@ impl CoreSurface {
|
||||
return;
|
||||
}
|
||||
|
||||
let mapped = compositor::with_states(&wl_surface, |data| {
|
||||
data.data_map
|
||||
.get::<RendererSurfaceStateUserData>()
|
||||
.map(|surface_states| surface_states.lock().unwrap().buffer().is_some())
|
||||
.unwrap_or(false)
|
||||
});
|
||||
self.update_textures(renderer);
|
||||
self.apply_surface_materials();
|
||||
}
|
||||
|
||||
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 {
|
||||
return;
|
||||
}
|
||||
|
||||
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 {
|
||||
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(smithay_tex) = wl_surface
|
||||
.get_data_raw::<RendererSurfaceStateUserData, _, _>(|surface_states| {
|
||||
surface_states
|
||||
.lock()
|
||||
.unwrap()
|
||||
.texture::<GlesRenderer>(renderer.id())
|
||||
.cloned()
|
||||
})
|
||||
.flatten()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(material_offset) = self.material_offset.lock().delta() {
|
||||
sk_mat.lock().0.queue_offset(*material_offset as i32);
|
||||
}
|
||||
let Some(sk_tex) = self.sk_tex.get() else {
|
||||
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 {
|
||||
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);
|
||||
});
|
||||
drop(mapped_data);
|
||||
self.apply_surface_materials();
|
||||
if let Some(material_offset) = self.material_offset.lock().delta() {
|
||||
sk_mat.lock().0.queue_offset(*material_offset as i32);
|
||||
}
|
||||
|
||||
let Some(surface_size) = wl_surface
|
||||
.get_data_raw::<RendererSurfaceStateUserData, _, _>(|surface_states| {
|
||||
surface_states.lock().unwrap().surface_size()
|
||||
})
|
||||
.flatten()
|
||||
else {
|
||||
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) {
|
||||
@@ -201,11 +207,6 @@ impl CoreSurface {
|
||||
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>> {
|
||||
self.mapped_data.lock().as_ref().map(|d| d.size)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use parking_lot::Mutex;
|
||||
use rand::Rng;
|
||||
use rustc_hash::FxHashMap;
|
||||
use smithay::{
|
||||
backend::renderer::utils::RendererSurfaceStateUserData,
|
||||
delegate_xdg_shell,
|
||||
reexports::{
|
||||
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
|
||||
.get_data::<Weak<PanelItem<XdgBackend>>>()
|
||||
.as_ref()
|
||||
@@ -119,14 +120,18 @@ impl XdgShellHandler for WaylandState {
|
||||
let Some(panel_item) = surface_panel_item(surf) else {
|
||||
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;
|
||||
};
|
||||
let size = [size.w as u32, size.h as u32].into();
|
||||
surf.get_data_raw::<Mutex<Vector2<u32>>, _, _>(|old_size| {
|
||||
let mut old_size = old_size.lock();
|
||||
let Some(size) = core_surface.size() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if *old_size != size {
|
||||
panel_item.toplevel_size_changed(size);
|
||||
*old_size = size;
|
||||
@@ -295,13 +300,15 @@ delegate_xdg_shell!(WaylandState);
|
||||
|
||||
pub struct XdgBackend {
|
||||
toplevel: Mutex<Option<ToplevelSurface>>,
|
||||
pub subsurfaces: Mutex<FxHashMap<u64, WlSurface>>,
|
||||
popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
|
||||
pub seat: Arc<SeatWrapper>,
|
||||
seat: Arc<SeatWrapper>,
|
||||
}
|
||||
impl XdgBackend {
|
||||
pub fn create(toplevel: ToplevelSurface, seat: Arc<SeatWrapper>) -> Self {
|
||||
XdgBackend {
|
||||
toplevel: Mutex::new(Some(toplevel)),
|
||||
subsurfaces: Mutex::new(FxHashMap::default()),
|
||||
popups: Mutex::new(FxHashMap::default()),
|
||||
seat,
|
||||
}
|
||||
@@ -319,6 +326,24 @@ impl XdgBackend {
|
||||
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) {
|
||||
let Some(panel_item) = self.panel_item() else {
|
||||
return;
|
||||
@@ -347,6 +372,7 @@ impl XdgBackend {
|
||||
return;
|
||||
};
|
||||
panel_item.destroy_child(id);
|
||||
self.popups.lock().remove(&id);
|
||||
}
|
||||
|
||||
fn child_data(&self, id: u64) -> Option<ChildInfo> {
|
||||
|
||||
Reference in New Issue
Block a user