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 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);
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
Reference in New Issue
Block a user