feat(wayland): configure and commit for toplevel]
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::{
|
||||
nodes::drawable::model::Model,
|
||||
};
|
||||
use mint::Vector2;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use send_wrapper::SendWrapper;
|
||||
use slog::Logger;
|
||||
@@ -35,112 +36,75 @@ pub static CORE_SURFACES: Registry<CoreSurface> = Registry::new();
|
||||
|
||||
pub struct CoreSurfaceData {
|
||||
wl_tex: Option<SendWrapper<Gles2Texture>>,
|
||||
sk_tex: Option<SendWrapper<SKTexture>>,
|
||||
sk_mat: Option<Arc<SendWrapper<Material>>>,
|
||||
pub size: Vector2<u32>,
|
||||
}
|
||||
impl CoreSurfaceData {
|
||||
fn new(sk: &StereoKit) -> Self {
|
||||
let sk_tex = SendWrapper::new(
|
||||
SKTexture::create(sk, TextureType::ImageNoMips, TextureFormat::RGBA32).unwrap(),
|
||||
);
|
||||
let sk_mat = {
|
||||
let shader = Shader::from_mem(sk, PANEL_SHADER_BYTES).unwrap();
|
||||
let mat = Material::create(sk, &shader).unwrap();
|
||||
mat.set_parameter("diffuse", &*sk_tex);
|
||||
mat.set_transparency(Transparency::Blend);
|
||||
Arc::new(SendWrapper::new(mat))
|
||||
};
|
||||
CoreSurfaceData {
|
||||
wl_tex: None,
|
||||
sk_tex: Some(sk_tex),
|
||||
sk_mat: Some(sk_mat),
|
||||
size: Vector2::from([0, 0]),
|
||||
}
|
||||
}
|
||||
fn update_tex(
|
||||
&mut self,
|
||||
surface: &CoreSurface,
|
||||
data: &RendererSurfaceStateUserData,
|
||||
renderer_id: usize,
|
||||
) {
|
||||
if let Some(surface_size) = data.borrow().surface_size() {
|
||||
self.size = Vector2::from([surface_size.w as u32, surface_size.h as u32]);
|
||||
}
|
||||
self.wl_tex = data
|
||||
.borrow()
|
||||
.texture::<Gles2Renderer>(renderer_id)
|
||||
.cloned()
|
||||
.map(SendWrapper::new);
|
||||
if let Some(smithay_tex) = self.wl_tex.as_ref() {
|
||||
let sk_tex = self.sk_tex.as_ref().unwrap();
|
||||
unsafe {
|
||||
sk_tex.set_native(
|
||||
smithay_tex.tex_id() as usize,
|
||||
smithay::backend::renderer::gles2::ffi::RGBA8.into(),
|
||||
TextureType::ImageNoMips,
|
||||
smithay_tex.width(),
|
||||
smithay_tex.height(),
|
||||
false,
|
||||
);
|
||||
sk_tex.set_sample(TextureSample::Point);
|
||||
sk_tex.set_address_mode(TextureAddress::Clamp);
|
||||
}
|
||||
}
|
||||
if let Some(sk_mat) = &self.sk_mat {
|
||||
if let Some(material_offset) = surface.material_offset.lock().delta() {
|
||||
sk_mat.set_queue_offset(*material_offset as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for CoreSurfaceData {
|
||||
fn drop(&mut self) {
|
||||
destroy_queue::add(self.wl_tex.take());
|
||||
destroy_queue::add(self.sk_tex.take());
|
||||
destroy_queue::add(self.sk_mat.take());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CoreSurface {
|
||||
display: Weak<Mutex<Display<WaylandState>>>,
|
||||
pub state: Weak<Mutex<WaylandState>>,
|
||||
pub dh: DisplayHandle,
|
||||
pub weak_surface: wayland_server::Weak<WlSurface>,
|
||||
mapped_data: Mutex<Option<CoreSurfaceData>>,
|
||||
sk_tex: OnceCell<SendWrapper<SKTexture>>,
|
||||
sk_mat: OnceCell<Arc<SendWrapper<Material>>>,
|
||||
material_offset: Mutex<Delta<u32>>,
|
||||
pub pending_material_applications: Mutex<Vec<(Arc<Model>, u32)>>,
|
||||
}
|
||||
|
||||
impl CoreSurface {
|
||||
pub fn new(
|
||||
state: &Arc<Mutex<WaylandState>>,
|
||||
pub fn add_to(
|
||||
display: &Arc<Mutex<Display<WaylandState>>>,
|
||||
dh: DisplayHandle,
|
||||
surface: &WlSurface,
|
||||
) -> Arc<Self> {
|
||||
CORE_SURFACES.add(CoreSurface {
|
||||
display: Arc::downgrade(display),
|
||||
state: Arc::downgrade(state),
|
||||
dh,
|
||||
weak_surface: surface.downgrade(),
|
||||
mapped_data: Mutex::new(None),
|
||||
material_offset: Mutex::new(Delta::new(0)),
|
||||
pending_material_applications: Mutex::new(Vec::new()),
|
||||
) {
|
||||
compositor::with_states(surface, |data| {
|
||||
data.data_map.insert_if_missing_threadsafe(|| {
|
||||
CORE_SURFACES.add(CoreSurface {
|
||||
display: Arc::downgrade(display),
|
||||
dh,
|
||||
weak_surface: surface.downgrade(),
|
||||
mapped_data: Mutex::new(None),
|
||||
sk_tex: OnceCell::new(),
|
||||
sk_mat: OnceCell::new(),
|
||||
material_offset: Mutex::new(Delta::new(0)),
|
||||
pending_material_applications: Mutex::new(Vec::new()),
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn from_wl_surface(surf: &WlSurface) -> Option<Arc<CoreSurface>> {
|
||||
compositor::with_states(surf, |data| {
|
||||
data.data_map.get::<Arc<CoreSurface>>().cloned()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process<F: FnOnce(&SurfaceData), M: FnOnce(&SurfaceData)>(
|
||||
pub fn process(
|
||||
&self,
|
||||
sk: &StereoKit,
|
||||
renderer: &mut Gles2Renderer,
|
||||
output: Output,
|
||||
log: &Logger,
|
||||
on_mapped: F,
|
||||
if_mapped: M,
|
||||
) {
|
||||
let Some(wl_surface) = self.wl_surface() else { return };
|
||||
|
||||
let sk_tex = self.sk_tex.get_or_init(|| {
|
||||
SendWrapper::new(
|
||||
SKTexture::create(sk, TextureType::ImageNoMips, TextureFormat::RGBA32).unwrap(),
|
||||
)
|
||||
});
|
||||
self.sk_mat.get_or_init(|| {
|
||||
let shader = Shader::from_mem(sk, PANEL_SHADER_BYTES).unwrap();
|
||||
let mat = Material::create(sk, &shader).unwrap();
|
||||
mat.set_parameter("diffuse", &**sk_tex);
|
||||
mat.set_transparency(Transparency::Blend);
|
||||
Arc::new(SendWrapper::new(mat))
|
||||
});
|
||||
|
||||
// Let smithay handle buffer management (has to be done here as RendererSurfaceStates is not thread safe)
|
||||
on_commit_buffer_handler(&wl_surface);
|
||||
// Import all surface buffers into textures
|
||||
@@ -160,26 +124,44 @@ impl CoreSurface {
|
||||
}
|
||||
|
||||
let mut mapped_data = self.mapped_data.lock();
|
||||
let just_mapped = mapped_data.is_none();
|
||||
if just_mapped {
|
||||
*mapped_data = Some(CoreSurfaceData::new(sk));
|
||||
}
|
||||
drop(mapped_data);
|
||||
self.with_states(|data| {
|
||||
self.with_data(|mapped_data| {
|
||||
mapped_data.update_tex(
|
||||
self,
|
||||
data.data_map.get::<RendererSurfaceStateUserData>().unwrap(),
|
||||
renderer.id(),
|
||||
);
|
||||
});
|
||||
self.apply_surface_materials();
|
||||
|
||||
let just_mapped = mapped_data.is_none();
|
||||
if just_mapped {
|
||||
on_mapped(data);
|
||||
let smithay_tex = data
|
||||
.data_map
|
||||
.get::<RendererSurfaceStateUserData>()
|
||||
.unwrap()
|
||||
.borrow()
|
||||
.texture::<Gles2Renderer>(renderer.id())
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
let sk_tex = self.sk_tex.get().unwrap();
|
||||
let sk_mat = self.sk_mat.get().unwrap();
|
||||
unsafe {
|
||||
sk_tex.set_native(
|
||||
smithay_tex.tex_id() as usize,
|
||||
smithay::backend::renderer::gles2::ffi::RGBA8.into(),
|
||||
TextureType::ImageNoMips,
|
||||
smithay_tex.width(),
|
||||
smithay_tex.height(),
|
||||
false,
|
||||
);
|
||||
sk_tex.set_sample(TextureSample::Point);
|
||||
sk_tex.set_address_mode(TextureAddress::Clamp);
|
||||
}
|
||||
if let Some(material_offset) = self.material_offset.lock().delta() {
|
||||
sk_mat.set_queue_offset(*material_offset as i32);
|
||||
}
|
||||
|
||||
let new_mapped_data = CoreSurfaceData {
|
||||
size: Vector2::from([smithay_tex.width(), smithay_tex.height()]),
|
||||
wl_tex: Some(SendWrapper::new(smithay_tex)),
|
||||
};
|
||||
*mapped_data = Some(new_mapped_data);
|
||||
}
|
||||
if_mapped(data);
|
||||
});
|
||||
self.apply_surface_materials();
|
||||
|
||||
send_frames_surface_tree(
|
||||
&wl_surface,
|
||||
@@ -190,6 +172,10 @@ impl CoreSurface {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn mapped(&self) -> bool {
|
||||
self.mapped_data.lock().is_some()
|
||||
}
|
||||
|
||||
pub fn set_material_offset(&self, material_offset: u32) {
|
||||
*self.material_offset.lock().value_mut() = material_offset;
|
||||
}
|
||||
@@ -201,32 +187,12 @@ impl CoreSurface {
|
||||
}
|
||||
|
||||
fn apply_surface_materials(&self) {
|
||||
self.with_data(|mapped_data| {
|
||||
let mut pending_material_applications = self.pending_material_applications.lock();
|
||||
for (model, material_idx) in &*pending_material_applications {
|
||||
model
|
||||
.pending_material_replacements
|
||||
.lock()
|
||||
.insert(*material_idx, mapped_data.sk_mat.clone().unwrap());
|
||||
}
|
||||
pending_material_applications.clear();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn pid(&self) -> Option<i32> {
|
||||
Some(
|
||||
self.weak_surface
|
||||
.upgrade()
|
||||
.ok()?
|
||||
.client()?
|
||||
.get_credentials(&self.dh)
|
||||
.ok()?
|
||||
.pid,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn wayland_state(&self) -> Arc<Mutex<WaylandState>> {
|
||||
self.state.upgrade().unwrap()
|
||||
for (model, material_idx) in self.pending_material_applications.lock().drain(0..) {
|
||||
model
|
||||
.pending_material_replacements
|
||||
.lock()
|
||||
.insert(material_idx, self.sk_mat.get().unwrap().clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wl_surface(&self) -> Option<WlSurface> {
|
||||
@@ -260,5 +226,8 @@ impl CoreSurface {
|
||||
impl Drop for CoreSurface {
|
||||
fn drop(&mut self) {
|
||||
CORE_SURFACES.remove(self);
|
||||
|
||||
destroy_queue::add(self.sk_tex.take());
|
||||
destroy_queue::add(self.sk_mat.take());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user