feat(wayland): fully async!!!

This commit is contained in:
Nova
2022-09-04 00:35:44 -04:00
parent a42834063e
commit 50161ed87d
12 changed files with 328 additions and 211 deletions

12
src/core/destroy_queue.rs Normal file
View File

@@ -0,0 +1,12 @@
use parking_lot::Mutex;
use std::any::Any;
static MAIN_DESTROY_QUEUE: Mutex<Vec<Box<dyn Any + Send + Sync>>> = Mutex::new(Vec::new());
pub fn add<T: Any + Sync + Send>(thing: T) {
MAIN_DESTROY_QUEUE.lock().push(Box::new(thing));
}
pub fn clear() {
MAIN_DESTROY_QUEUE.lock().clear();
}

View File

@@ -1,3 +1,4 @@
pub mod destroy_queue;
pub mod resource;
pub mod client;
pub mod eventloop;

View File

@@ -2,21 +2,18 @@ mod core;
mod nodes;
mod wayland;
use crate::core::destroy_queue;
use crate::nodes::model::{MODELS_TO_DROP, MODEL_REGISTRY};
use crate::wayland::WaylandState;
use crate::wayland::Wayland;
use self::core::eventloop::EventLoop;
use anyhow::Result;
use clap::Parser;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use slog::Drain;
use std::sync::Arc;
use stereokit::{lifecycle::DisplayMode, Settings};
use tokio::{runtime::Handle, sync::oneshot};
static TOKIO_HANDLE: Lazy<Mutex<Option<Handle>>> = Lazy::new(Default::default);
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
struct CliArgs {
@@ -56,15 +53,18 @@ fn main() -> Result<()> {
}
let (event_stop_tx, event_stop_rx) = oneshot::channel::<()>();
let (handle_sender, handle_receiver) = oneshot::channel::<Handle>();
let event_thread = std::thread::Builder::new()
.name("event_loop".to_owned())
.spawn(move || event_loop(event_stop_rx))?;
.spawn(move || event_loop(handle_sender, event_stop_rx))?;
let _tokio_handle = handle_receiver.blocking_recv()?.enter();
let mut wayland = WaylandState::new(log)?;
let mut wayland = Wayland::new(log)?;
println!("Stardust ready!");
stereokit.run(
|draw_ctx| {
wayland.frame(&stereokit);
destroy_queue::clear();
nodes::root::Root::logic_step(stereokit.time_elapsed());
for model in MODEL_REGISTRY.get_valid_contents() {
@@ -72,7 +72,7 @@ fn main() -> Result<()> {
}
MODELS_TO_DROP.lock().clear();
unsafe { wayland.renderer.egl_context().make_current().unwrap() };
wayland.make_context_current();
},
|| {
println!("Cleanly shut down StereoKit");
@@ -89,9 +89,14 @@ fn main() -> Result<()> {
Ok(())
}
#[tokio::main]
async fn event_loop(stop_rx: oneshot::Receiver<()>) -> anyhow::Result<()> {
TOKIO_HANDLE.lock().replace(Handle::current());
// #[tokio::main]
#[tokio::main(flavor = "current_thread")]
async fn event_loop(
handle_sender: oneshot::Sender<Handle>,
stop_rx: oneshot::Receiver<()>,
) -> anyhow::Result<()> {
let _ = handle_sender.send(Handle::current());
// console_subscriber::init();
let (event_loop, event_loop_join_handle) =
EventLoop::new().expect("Couldn't create server socket");

View File

@@ -6,7 +6,6 @@ use super::model::Model;
use super::spatial::Spatial;
use crate::core::client::Client;
use crate::core::registry::Registry;
use crate::TOKIO_HANDLE;
use anyhow::{anyhow, Result};
use libstardustxr::scenegraph::ScenegraphError;
use nanoid::nanoid;
@@ -175,7 +174,7 @@ impl Node {
let path = self.path.clone();
let method = method.to_string();
let data = data.to_vec();
TOKIO_HANDLE.lock().as_ref().unwrap().spawn(async move {
tokio::spawn(async move {
if let Some(messenger) = client.messenger.as_ref() {
let _ = messenger
.send_remote_signal(path.as_str(), method.as_str(), data.as_slice())

View File

@@ -1,20 +1,11 @@
use std::sync::Arc;
use super::state::WaylandState;
use crate::nodes::{core::Node, item::ItemType};
use super::{panel_item::PanelItem, surface::CoreSurface, WaylandState};
use send_wrapper::SendWrapper;
use smithay::{
backend::renderer::utils::{
import_surface_tree, on_commit_buffer_handler, RendererSurfaceStateUserData,
},
delegate_compositor,
reexports::wayland_server::protocol::wl_surface::WlSurface,
wayland::{
compositor::{self, CompositorHandler, CompositorState},
shell::xdg::XdgToplevelSurfaceData,
},
wayland::compositor::{self, CompositorHandler, CompositorState},
};
use std::sync::Arc;
impl CompositorHandler for WaylandState {
fn compositor_state(&mut self) -> &mut CompositorState {
@@ -22,40 +13,12 @@ impl CompositorHandler for WaylandState {
}
fn commit(&mut self, surface: &WlSurface) {
// Let Smithay handle all the buffer maintenance
on_commit_buffer_handler(surface);
// Create/update textures from all buffers
import_surface_tree(&mut self.renderer, surface, &self.log).unwrap();
compositor::with_states(surface, |data| {
let mapped = data
.data_map
.get::<RendererSurfaceStateUserData>()
.map(|surface_states| surface_states.borrow().wl_buffer().is_some())
.unwrap_or(false);
if !mapped || data.data_map.get::<XdgToplevelSurfaceData>().is_none() {
return;
}
data.data_map.insert_if_missing_threadsafe(CoreSurface::new);
data.data_map.insert_if_missing_threadsafe(|| {
PanelItem::create(&self.display_handle, &data.data_map, surface.clone())
});
let surface_states = data.data_map.get::<RendererSurfaceStateUserData>().unwrap();
let core_surface = data.data_map.get::<CoreSurface>().unwrap();
*core_surface.wl_tex.lock() = surface_states
.borrow()
.texture(&self.renderer)
.cloned()
.map(SendWrapper::new);
let panel_node = data.data_map.get::<Arc<Node>>().unwrap();
let item = panel_node.item.get().unwrap();
if let ItemType::Panel(panel_item) = &item.specialization {
panel_item.resize(&data.data_map);
if let Some(panel_node) = data.data_map.get::<Arc<Node>>() {
let item = panel_node.item.get().unwrap();
if let ItemType::Panel(panel_item) = &item.specialization {
panel_item.resize(&data.data_map);
}
}
});
}

View File

@@ -2,40 +2,44 @@ pub mod compositor;
pub mod panel_item;
pub mod seat;
pub mod shaders;
pub mod state;
pub mod surface;
pub mod xdg_decoration;
pub mod xdg_shell;
use self::{panel_item::PanelItem, seat::SeatDelegate};
use crate::nodes::core::Node;
use self::{panel_item::PanelItem, state::WaylandState};
use crate::{nodes::core::Node, wayland::state::ClientState};
use anyhow::{ensure, Result};
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use send_wrapper::SendWrapper;
use slog::Logger;
use smithay::{
backend::{egl::EGLContext, renderer::gles2::Gles2Renderer},
delegate_output, delegate_shm,
backend::{
egl::EGLContext,
renderer::{
gles2::Gles2Renderer,
utils::{import_surface_tree, on_commit_buffer_handler, RendererSurfaceStateUserData},
},
},
desktop::utils::send_frames_surface_tree,
reexports::wayland_server::{
backend::{ClientData, ClientId, DisconnectReason, GlobalId},
protocol::wl_output::Subpixel,
Display, DisplayHandle, ListeningSocket,
},
utils::Size,
wayland::{
buffer::BufferHandler,
compositor::{with_states, CompositorState},
output::{Output, OutputManagerState, Scale::Integer},
shell::xdg::{decoration::XdgDecorationState, XdgShellState},
shm::{ShmHandler, ShmState},
},
reexports::wayland_server::{backend::GlobalId, Display, ListeningSocket},
wayland::{compositor::with_states, shell::xdg::XdgToplevelSurfaceData},
};
use std::os::unix::prelude::AsRawFd;
use std::{
ffi::c_void,
os::unix::{
net::UnixListener,
prelude::{FromRawFd, RawFd},
},
sync::Arc,
};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::{ffi::c_void, sync::Arc};
use stereokit as sk;
use stereokit::StereoKit;
use surface::CoreSurface;
use tokio::{
io::unix::AsyncFd, net::UnixListener as AsyncUnixListener, sync::mpsc, task::JoinHandle,
};
struct EGLRawHandles {
display: *const c_void,
@@ -58,43 +62,17 @@ fn get_sk_egl() -> Result<EGLRawHandles> {
})
}
pub struct ClientState;
impl ClientData for ClientState {
fn initialized(&self, client_id: ClientId) {
println!("Wayland client {:?} connected", client_id);
}
static GLOBAL_DESTROY_QUEUE: OnceCell<mpsc::Sender<GlobalId>> = OnceCell::new();
fn disconnected(&self, client_id: ClientId, reason: DisconnectReason) {
println!(
"Wayland client {:?} disconnected because {:#?}",
client_id, reason
);
}
pub struct Wayland {
log: slog::Logger,
display: Arc<Mutex<Display<WaylandState>>>,
join_handle: JoinHandle<Result<()>>,
renderer: Gles2Renderer,
state: Arc<Mutex<WaylandState>>,
}
lazy_static::lazy_static! {
static ref GLOBAL_DESTROY_QUEUE_IN: OnceCell<SendWrapper<Sender<GlobalId>>> = OnceCell::new();
}
pub struct WaylandState {
pub log: slog::Logger,
global_destroy_queue: Receiver<GlobalId>,
pub display: Arc<Mutex<Display<WaylandState>>>,
pub display_handle: DisplayHandle,
pub socket: ListeningSocket,
pub renderer: Gles2Renderer,
pub compositor_state: CompositorState,
pub xdg_shell_state: XdgShellState,
pub xdg_decoration_state: XdgDecorationState,
pub shm_state: ShmState,
pub output_manager_state: OutputManagerState,
pub output: Output,
pub seat_state: SeatDelegate,
// pub data_device_state: DataDeviceState,
}
impl WaylandState {
impl Wayland {
pub fn new(log: Logger) -> Result<Self> {
let egl_raw_handles = get_sk_egl()?;
let renderer = unsafe {
@@ -110,104 +88,124 @@ impl WaylandState {
};
let display: Display<WaylandState> = Display::new()?;
let display_handle = display.handle();
let display = Arc::new(Mutex::new(display));
let state = Arc::new(Mutex::new(WaylandState::new(
log.clone(),
display_handle.clone(),
)));
let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8);
GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap();
let join_handle =
Wayland::start_loop(display.clone(), state.clone(), global_destroy_queue)?;
Ok(Wayland {
log,
display,
join_handle,
renderer,
state,
})
}
fn start_loop(
display: Arc<Mutex<Display<WaylandState>>>,
state: Arc<Mutex<WaylandState>>,
mut global_destroy_queue: mpsc::Receiver<GlobalId>,
) -> Result<JoinHandle<Result<()>>> {
let socket = ListeningSocket::bind_auto("wayland", 0..33)?;
if let Some(socket_name) = socket.socket_name() {
println!("Wayland compositor {:?} active", socket_name);
}
let display_handle = display.handle();
let compositor_state = CompositorState::new::<Self, _>(&display_handle, log.clone());
let xdg_shell_state = XdgShellState::new::<Self, _>(&display_handle, log.clone());
let xdg_decoration_state = XdgDecorationState::new::<Self, _>(&display_handle, log.clone());
let shm_state = ShmState::new::<Self, _>(&display_handle, vec![], log.clone());
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
let output = Output::new(
"1x".to_owned(),
smithay::wayland::output::PhysicalProperties {
size: Size::default(),
subpixel: Subpixel::None,
make: "Virtual XR Display".to_owned(),
model: "Your Headset Name Here".to_owned(),
},
log.clone(),
);
let _global = output.create_global::<Self>(&display_handle);
output.change_current_state(None, None, Some(Integer(2)), None);
// let data_device_state = DataDeviceState::new(&dh, log.clone());
let listen_async =
AsyncUnixListener::from_std(unsafe { UnixListener::from_raw_fd(socket.as_raw_fd()) })?;
let (global_destroy_queue_in, global_destroy_queue) = channel();
GLOBAL_DESTROY_QUEUE_IN
.set(SendWrapper::new(global_destroy_queue_in))
.unwrap();
let dispatch_poll_fd: RawFd = display.lock().backend().poll_fd();
let dispatch_poll_listener = AsyncFd::new(dispatch_poll_fd)?;
println!("Init Wayland compositor");
Ok(WaylandState {
log,
let dh1 = display.lock().handle();
let mut dh2 = dh1.clone();
global_destroy_queue,
display: Arc::new(Mutex::new(display)),
display_handle,
socket,
renderer,
compositor_state,
xdg_shell_state,
xdg_decoration_state,
shm_state,
output_manager_state,
output,
seat_state: SeatDelegate,
// data_device_state,
})
Ok(tokio::task::spawn(async move {
let _socket = socket; // Keep the socket alive
loop {
tokio::select! {
e = global_destroy_queue.recv() => { // New global to destroy
dh1.remove_global::<WaylandState>(e.unwrap());
}
acc = listen_async.accept() => { // New client connected
let (stream, _) = acc?;
dh2.insert_client(stream.into_std()?, Arc::new(ClientState))?;
}
e = dispatch_poll_listener.readable() => { // Dispatch
let mut guard = e?;
let mut display = display.lock();
display.dispatch_clients(&mut *state.lock())?;
display.flush_clients()?;
guard.clear_ready();
}
}
}
}))
}
pub fn frame(&mut self, sk: &StereoKit) {
let display_clone = self.display.clone();
let mut display = display_clone.lock();
if let Ok(Some(client)) = self.socket.accept() {
let _ = display
.handle()
.insert_client(client, Arc::new(ClientState));
}
display.dispatch_clients(self).unwrap();
while let Ok(global_to_destroy) = self.global_destroy_queue.try_recv() {
self.display_handle
.remove_global::<WaylandState>(global_to_destroy);
}
let log = self.log.clone();
let time_ms = (sk.time_getf() * 1000.) as u32;
self.xdg_shell_state.toplevel_surfaces(|surfs| {
for surf in surfs.iter() {
with_states(surf.wl_surface(), |data| {
let toplevel_surfaces = self
.state
.lock()
.xdg_shell_state
.toplevel_surfaces(|surfs| surfs.to_vec());
for surf in toplevel_surfaces {
// Let Smithay handle all the buffer maintenance
on_commit_buffer_handler(surf.wl_surface());
// Import all surface buffers into textures
import_surface_tree(&mut self.renderer, surf.wl_surface(), &log).unwrap();
with_states(surf.wl_surface(), |data| {
let mapped = data
.data_map
.get::<RendererSurfaceStateUserData>()
.map(|surface_states| surface_states.borrow().wl_buffer().is_some())
.unwrap_or(false);
if mapped && data.data_map.get::<XdgToplevelSurfaceData>().is_some() {
data.data_map.insert_if_missing_threadsafe(CoreSurface::new);
data.data_map.insert_if_missing_threadsafe(|| {
PanelItem::create(
&self.display,
self.display.lock().handle(),
&data.data_map,
surf.wl_surface().clone(),
)
});
if let Some(core_surface) = data.data_map.get::<CoreSurface>() {
core_surface.update_tex(sk);
core_surface.update_tex(sk, data, &self.renderer);
if let Some(panel_item) = data.data_map.get::<Arc<Node>>() {
PanelItem::apply_surface_materials(panel_item, core_surface);
}
}
});
send_frames_surface_tree(surf.wl_surface(), time_ms);
}
});
display.flush_clients().unwrap();
}
});
send_frames_surface_tree(surf.wl_surface(), time_ms);
}
self.display.lock().flush_clients().unwrap();
}
pub fn make_context_current(&self) {
unsafe {
self.renderer.egl_context().make_current().unwrap();
}
}
}
impl Drop for WaylandState {
impl Drop for Wayland {
fn drop(&mut self) {
println!("Cleanly shut down the Wayland compositor");
self.join_handle.abort();
}
}
impl BufferHandler for WaylandState {
fn buffer_destroyed(
&mut self,
_buffer: &smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer,
) {
}
}
impl ShmHandler for WaylandState {
fn shm_state(&self) -> &smithay::wayland::shm::ShmState {
&self.shm_state
}
}
delegate_shm!(WaylandState);
delegate_output!(WaylandState);

View File

@@ -1,3 +1,4 @@
use super::{seat::SeatData, state::WaylandState, surface::CoreSurface, GLOBAL_DESTROY_QUEUE};
use crate::{
core::{
client::{Client, INTERNAL_CLIENT},
@@ -25,7 +26,7 @@ use smithay::{
wl_pointer::{Axis, ButtonState},
wl_surface::WlSurface,
},
DisplayHandle, Resource,
Display, DisplayHandle, Resource,
},
utils::{user_data::UserDataMap, Logical, Size},
};
@@ -34,8 +35,6 @@ use std::{
sync::{Arc, Weak},
};
use super::{seat::SeatData, surface::CoreSurface, GLOBAL_DESTROY_QUEUE_IN};
lazy_static! {
static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
type_name: "panel",
@@ -63,6 +62,7 @@ lazy_static! {
pub struct PanelItem {
node: Weak<Node>,
pending_material_applications: Mutex<Vec<(Arc<Model>, u32)>>,
display: Weak<Mutex<Display<WaylandState>>>,
dh: DisplayHandle,
pub toplevel_surface_id: ObjectId,
seat_data: SeatData,
@@ -70,7 +70,8 @@ pub struct PanelItem {
}
impl PanelItem {
pub fn create(
dh: &DisplayHandle,
display: &Arc<Mutex<Display<WaylandState>>>,
dh: DisplayHandle,
data: &UserDataMap,
toplevel_surface: WlSurface,
) -> Arc<Node> {
@@ -82,7 +83,7 @@ impl PanelItem {
));
Spatial::add_to(&node, None, Mat4::IDENTITY).unwrap();
let seat_data = SeatData::new(dh, toplevel_surface.client_id().unwrap());
let seat_data = SeatData::new(&dh, toplevel_surface.client_id().unwrap());
let size = data
.get::<RendererSurfaceStateUserData>()
@@ -95,7 +96,8 @@ impl PanelItem {
let specialization = ItemType::Panel(PanelItem {
node: Arc::downgrade(&node),
pending_material_applications: Mutex::new(Vec::new()),
dh: dh.clone(),
display: Arc::downgrade(display),
dh,
toplevel_surface_id: toplevel_surface.id(),
seat_data,
size,
@@ -124,10 +126,18 @@ impl PanelItem {
fn toplevel_surface(&self) -> WlSurface {
WlSurface::from_id(&self.dh, self.toplevel_surface_id.clone()).unwrap()
}
fn flush_clients(&self) {
self.display
.upgrade()
.unwrap()
.lock()
.flush_clients()
.unwrap();
}
pub fn resize(&self, data: &UserDataMap) {
if let Some(surface_states) = data.get::<RendererSurfaceStateUserData>() {
if let Some(size) = surface_states.borrow().surface_size() {
if let Some(size) = surface_states.borrow().buffer_size() {
*self.size.lock() = size;
let _ = self.node.upgrade().unwrap().send_remote_signal(
"resize",
@@ -190,6 +200,8 @@ impl PanelItem {
if let Some(pointer) = panel_item.seat_data.pointer() {
pointer.leave(0, &panel_item.toplevel_surface());
*panel_item.seat_data.pointer_active.lock() = false;
pointer.frame();
panel_item.flush_clients();
}
}
}
@@ -211,6 +223,7 @@ impl PanelItem {
*pointer_active = true;
}
pointer.frame();
panel_item.flush_clients();
}
}
@@ -235,6 +248,7 @@ impl PanelItem {
},
);
pointer.frame();
panel_item.flush_clients();
}
}
}
@@ -263,6 +277,7 @@ impl PanelItem {
}
}
pointer.frame();
panel_item.flush_clients();
}
}
}
@@ -349,11 +364,8 @@ impl ItemSpecialization for PanelItem {
}
impl Drop for PanelItem {
fn drop(&mut self) {
GLOBAL_DESTROY_QUEUE_IN
.get()
.unwrap()
.send(self.seat_data.global_id.get().cloned().unwrap())
.unwrap();
let id = self.seat_data.global_id.get().cloned().unwrap();
tokio::spawn(async move { GLOBAL_DESTROY_QUEUE.get().unwrap().send(id).await });
}
}

View File

@@ -1,4 +1,3 @@
use super::WaylandState;
use nanoid::nanoid;
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
@@ -16,6 +15,8 @@ use smithay::reexports::wayland_server::{
use std::ops::Deref;
use std::sync::Arc;
use super::state::WaylandState;
pub struct SeatDelegate;
#[derive(Clone)]

103
src/wayland/state.rs Normal file
View File

@@ -0,0 +1,103 @@
use slog::Logger;
use smithay::{
delegate_output, delegate_shm,
reexports::wayland_server::{
backend::{ClientData, ClientId, DisconnectReason},
protocol::wl_output::Subpixel,
DisplayHandle,
},
utils::Size,
wayland::{
buffer::BufferHandler,
compositor::CompositorState,
output::{Output, OutputManagerState, Scale},
shell::xdg::{decoration::XdgDecorationState, XdgShellState},
shm::{ShmHandler, ShmState},
},
};
use super::seat::SeatDelegate;
pub struct ClientState;
impl ClientData for ClientState {
fn initialized(&self, client_id: ClientId) {
println!("Wayland client {:?} connected", client_id);
}
fn disconnected(&self, client_id: ClientId, reason: DisconnectReason) {
println!(
"Wayland client {:?} disconnected because {:#?}",
client_id, reason
);
}
}
pub struct WaylandState {
pub display_handle: DisplayHandle,
pub compositor_state: CompositorState,
pub xdg_shell_state: XdgShellState,
pub xdg_decoration_state: XdgDecorationState,
pub shm_state: ShmState,
pub output_manager_state: OutputManagerState,
pub output: Output,
pub seat_state: SeatDelegate,
// pub data_device_state: DataDeviceState,
}
impl WaylandState {
pub fn new(log: Logger, display_handle: DisplayHandle) -> Self {
let compositor_state = CompositorState::new::<Self, _>(&display_handle, log.clone());
let xdg_shell_state = XdgShellState::new::<Self, _>(&display_handle, log.clone());
let xdg_decoration_state = XdgDecorationState::new::<Self, _>(&display_handle, log.clone());
let shm_state = ShmState::new::<Self, _>(&display_handle, vec![], log.clone());
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
let output = Output::new(
"1x".to_owned(),
smithay::wayland::output::PhysicalProperties {
size: Size::default(),
subpixel: Subpixel::None,
make: "Virtual XR Display".to_owned(),
model: "Your Headset Name Here".to_owned(),
},
log.clone(),
);
let _global = output.create_global::<Self>(&display_handle);
output.change_current_state(None, None, Some(Scale::Integer(2)), None);
// let data_device_state = DataDeviceState::new(&dh, log.clone());
println!("Init Wayland compositor");
WaylandState {
display_handle,
compositor_state,
xdg_shell_state,
xdg_decoration_state,
shm_state,
output_manager_state,
output,
seat_state: SeatDelegate,
// data_device_state,
}
}
}
impl Drop for WaylandState {
fn drop(&mut self) {
println!("Cleanly shut down the Wayland compositor");
}
}
impl BufferHandler for WaylandState {
fn buffer_destroyed(
&mut self,
_buffer: &smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer,
) {
}
}
impl ShmHandler for WaylandState {
fn shm_state(&self) -> &smithay::wayland::shm::ShmState {
&self.shm_state
}
}
delegate_shm!(WaylandState);
delegate_output!(WaylandState);

View File

@@ -1,10 +1,17 @@
use std::{fmt::Error, sync::Arc};
use std::{fmt::Error, mem, sync::Arc};
use glam::vec2;
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use send_wrapper::SendWrapper;
use smithay::backend::renderer::{gles2::Gles2Texture, Texture};
use smithay::{
backend::renderer::{
gles2::{Gles2Renderer, Gles2Texture},
utils::RendererSurfaceStateUserData,
Texture,
},
wayland::compositor::SurfaceData,
};
use stereokit::{
material::Material,
shader::Shader,
@@ -12,6 +19,8 @@ use stereokit::{
StereoKit,
};
use crate::core::destroy_queue;
use super::shaders::SIMULA_SHADER_BYTES;
pub struct CoreSurface {
@@ -29,7 +38,7 @@ impl CoreSurface {
}
}
pub fn update_tex(&self, sk: &StereoKit) {
pub fn update_tex(&self, sk: &StereoKit, data: &SurfaceData, renderer: &Gles2Renderer) {
let sk_tex = self
.sk_tex
.get_or_try_init(|| {
@@ -51,6 +60,14 @@ impl CoreSurface {
.map(|mat| Arc::new(SendWrapper::new(mat)))
})
.unwrap();
if let Some(surface_states) = data.data_map.get::<RendererSurfaceStateUserData>() {
*self.wl_tex.lock() = surface_states
.borrow()
.texture(renderer)
.cloned()
.map(SendWrapper::new);
}
if let Some(smithay_tex) = self.wl_tex.lock().as_ref() {
unsafe {
sk_tex.set_native(
@@ -70,3 +87,10 @@ impl CoreSurface {
}
}
}
impl Drop for CoreSurface {
fn drop(&mut self) {
destroy_queue::add(mem::replace(self.wl_tex.get_mut(), None));
self.sk_tex.take().map(destroy_queue::add);
self.sk_mat.take().map(destroy_queue::add);
}
}

View File

@@ -1,11 +1,10 @@
use super::state::WaylandState;
use smithay::{
delegate_xdg_decoration,
reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode,
wayland::shell::xdg::decoration::XdgDecorationHandler,
};
use super::WaylandState;
impl XdgDecorationHandler for WaylandState {
fn new_decoration(&mut self, toplevel: smithay::wayland::shell::xdg::ToplevelSurface) {
toplevel.with_pending_state(|state| {

View File

@@ -1,4 +1,4 @@
use super::WaylandState;
use super::state::WaylandState;
use smithay::{
delegate_xdg_shell,
reexports::{