From 63cf0db4482562097319ff4a32f11265adfda67d Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 10 Jul 2025 10:13:38 -0700 Subject: [PATCH] feat: dmatex!! (sorta, borken) --- Cargo.toml | 1 - src/core/client.rs | 4 - src/core/destroy_queue.rs | 23 --- src/core/graphics_info.rs | 7 - src/core/mod.rs | 2 - src/main.rs | 13 -- src/wayland/core/buffer.rs | 35 ++-- src/wayland/core/registry.rs | 6 +- src/wayland/core/surface.rs | 4 +- src/wayland/dmabuf/buffer_backing.rs | 242 ++++++++++----------------- src/wayland/dmabuf/buffer_params.rs | 15 +- src/wayland/mod.rs | 71 ++++---- 12 files changed, 146 insertions(+), 277 deletions(-) delete mode 100644 src/core/destroy_queue.rs delete mode 100644 src/core/graphics_info.rs diff --git a/Cargo.toml b/Cargo.toml index 3553245..968cd96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ wayland = [ "dep:drm-fourcc", "dep:memfd", ] -dmabuf = [] profile_tokio = ["dep:console-subscriber", "tokio/tracing"] profile_app = ["dep:tracing-tracy", "bevy/trace_tracy", "bevy/trace"] bevy_debugging = ["bevy/bevy_remote", "bevy/track_location"] diff --git a/src/core/client.rs b/src/core/client.rs index afcb5ca..dc1c6cb 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,6 +1,5 @@ use super::{ client_state::{CLIENT_STATES, ClientStateParsed}, - destroy_queue, scenegraph::Scenegraph, }; use crate::{ @@ -231,9 +230,6 @@ impl Client { if let Some(flush_join_handle) = self.flush_join_handle.get() { flush_join_handle.abort(); } - if let Some(client) = CLIENTS.remove(self) { - destroy_queue::add(client); - } } } impl Debug for Client { diff --git a/src/core/destroy_queue.rs b/src/core/destroy_queue.rs deleted file mode 100644 index f6e9d29..0000000 --- a/src/core/destroy_queue.rs +++ /dev/null @@ -1,23 +0,0 @@ -use parking_lot::Mutex; -use std::{any::Any, sync::LazyLock}; -use tokio::sync::mpsc::{self, unbounded_channel}; - -type Anything = Box; - -static MAIN_DESTROY_QUEUE: LazyLock<( - mpsc::UnboundedSender, - Mutex>, -)> = LazyLock::new(|| { - let (tx, rx) = unbounded_channel(); - (tx, Mutex::new(rx)) -}); - -pub fn add(thing: T) { - MAIN_DESTROY_QUEUE.0.send(Box::new(thing)).unwrap(); -} - -pub fn clear() { - while let Ok(thing) = MAIN_DESTROY_QUEUE.1.lock().try_recv() { - drop(thing) - } -} diff --git a/src/core/graphics_info.rs b/src/core/graphics_info.rs deleted file mode 100644 index b947d58..0000000 --- a/src/core/graphics_info.rs +++ /dev/null @@ -1,7 +0,0 @@ -use bevy::asset::Assets; -use bevy::ecs::world::Mut; -use bevy::image::Image; - -pub struct GraphicsInfo<'w> { - pub _images: Mut<'w, Assets>, -} diff --git a/src/core/mod.rs b/src/core/mod.rs index b6e4b63..d80bb4c 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -3,10 +3,8 @@ pub mod client; pub mod client_state; pub mod color; pub mod delta; -pub mod destroy_queue; pub mod entity_handle; pub mod error; -pub mod graphics_info; pub mod registry; pub mod resource; pub mod scenegraph; diff --git a/src/main.rs b/src/main.rs index a223044..87fd74d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,6 @@ mod session; #[cfg(feature = "wayland")] mod wayland; -use crate::core::destroy_queue; use crate::nodes::input; use bevy::MinimalPlugins; @@ -46,7 +45,6 @@ use bevy_mod_xr::session::{XrFirst, XrHandleEvents, XrSessionPlugin}; use clap::Parser; use core::client::{Client, tick_internal_client}; use core::entity_handle::EntityHandlePlugin; -use core::graphics_info::GraphicsInfo; use core::task; use directories::ProjectDirs; use nodes::audio::AudioNodePlugin; @@ -449,13 +447,6 @@ fn add_oit( } fn xr_step(world: &mut World) { - // camera::update(token); - #[cfg(feature = "wayland")] - Wayland::early_frame(&mut GraphicsInfo { - _images: world.resource_mut::>(), - }); - destroy_queue::clear(); - // update things like the Xr input methods world.run_schedule(PreFrameWait); input::process_input(); @@ -487,8 +478,4 @@ fn xr_step(world: &mut World) { } tick_internal_client(); - #[cfg(feature = "wayland")] - world.resource_scope::, _>(|world, mut materials| { - Wayland::update_graphics(&mut materials, &mut world.resource_mut::>()); - }); } diff --git a/src/wayland/core/buffer.rs b/src/wayland/core/buffer.rs index 95274f9..5d1fe01 100644 --- a/src/wayland/core/buffer.rs +++ b/src/wayland/core/buffer.rs @@ -1,17 +1,15 @@ use std::sync::{Arc, atomic::AtomicBool}; -#[cfg(feature = "dmabuf")] use crate::wayland::dmabuf::buffer_backing::DmabufBacking; use crate::{ core::registry::Registry, - wayland::{ - GraphicsInfo, MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt, - }, + wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt}, }; use bevy::{ asset::{Assets, Handle}, image::Image, }; +use bevy_dmabuf::import::ImportedDmatexs; use mint::Vector2; pub use waynest::server::protocol::core::wayland::wl_buffer::*; use waynest::{ @@ -19,12 +17,11 @@ use waynest::{ wire::ObjectId, }; -pub static BUFFER_REGISTRY: Registry = Registry::new(); +pub static WL_BUFFER_REGISTRY: Registry = Registry::new(); #[derive(Debug)] pub enum BufferBacking { Shm(ShmBufferBacking), - #[cfg(feature = "dmabuf")] Dmabuf(DmabufBacking), } impl BufferBacking { @@ -53,29 +50,21 @@ impl Buffer { rendered: AtomicBool::new(false), }, ); - BUFFER_REGISTRY.add_raw(&buffer); + WL_BUFFER_REGISTRY.add_raw(&buffer); buffer } - #[allow(unused)] - pub fn init_tex(self: Arc, graphics_info: &mut GraphicsInfo) { - match &self.backing { - BufferBacking::Shm(_) => (), - #[cfg(feature = "dmabuf")] - BufferBacking::Dmabuf(backing) => backing.init_tex(graphics_info, self.clone()), - } - } - /// Returns the tex if it was updated - pub fn update_tex(&self, images: &mut Assets) -> Option> { + pub fn update_tex( + &self, + dmatexes: &ImportedDmatexs, + images: &mut Assets, + buffer: Arc, + ) -> Option> { tracing::debug!("Updating texture for buffer {:?}", self.id); match &self.backing { BufferBacking::Shm(backing) => backing.update_tex(images), - #[cfg(feature = "dmabuf")] - BufferBacking::Dmabuf(backing) => backing - .get_tex() - .map(|tex| tex.get_id().to_string()) - .and_then(|tex_id| Tex::find(tex_id).ok()), + BufferBacking::Dmabuf(backing) => backing.update_tex(dmatexes, images, buffer), } } @@ -86,7 +75,6 @@ impl Buffer { pub fn is_transparent(&self) -> bool { match &self.backing { BufferBacking::Shm(backing) => backing.is_transparent(), - #[cfg(feature = "dmabuf")] BufferBacking::Dmabuf(backing) => backing.is_transparent(), } } @@ -94,7 +82,6 @@ impl Buffer { pub fn size(&self) -> Vector2 { match &self.backing { BufferBacking::Shm(backing) => backing.size(), - #[cfg(feature = "dmabuf")] BufferBacking::Dmabuf(backing) => backing.size(), } } diff --git a/src/wayland/core/registry.rs b/src/wayland/core/registry.rs index 23fcbe0..ddcd62b 100644 --- a/src/wayland/core/registry.rs +++ b/src/wayland/core/registry.rs @@ -6,10 +6,11 @@ use crate::wayland::{ seat::{Seat, WlSeat}, shm::{Shm, WlShm}, }, + dmabuf::Dmabuf, xdg::wm_base::{WmBase, XdgWmBase}, }; pub use waynest::server::protocol::core::wayland::wl_registry::*; -#[cfg(feature = "dmabuf")] + use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1; use waynest::{ server::{Client, Dispatcher, Error, Result}, @@ -23,7 +24,6 @@ impl RegistryGlobals { pub const WM_BASE: u32 = 2; pub const SEAT: u32 = 3; pub const OUTPUT: u32 = 4; - #[cfg(feature = "dmabuf")] pub const DMABUF: u32 = 5; } @@ -77,7 +77,6 @@ impl Registry { ) .await?; - #[cfg(feature = "dmabuf")] self.global( client, sender_id, @@ -131,7 +130,6 @@ impl WlRegistry for Registry { tracing::info!("Binding output"); client.insert(new_id.object_id, Output); } - #[cfg(feature = "dmabuf")] RegistryGlobals::DMABUF => { tracing::info!("Binding dmabuf"); let dmabuf = client.insert(new_id.object_id, Dmabuf::new()); diff --git a/src/wayland/core/surface.rs b/src/wayland/core/surface.rs index 198ff91..93f7d5d 100644 --- a/src/wayland/core/surface.rs +++ b/src/wayland/core/surface.rs @@ -14,6 +14,7 @@ use bevy::{ image::Image, render::alpha::AlphaMode, }; +use bevy_dmabuf::import::ImportedDmatexs; use mint::Vector2; use parking_lot::Mutex; use std::sync::{Arc, OnceLock, atomic::Ordering}; @@ -111,6 +112,7 @@ impl Surface { pub fn update_graphics( &self, + dmatexes: &ImportedDmatexs, materials: &mut Assets, images: &mut Assets, ) { @@ -139,7 +141,7 @@ impl Surface { }) }); - if let Some(new_tex) = buffer.update_tex(images) { + if let Some(new_tex) = buffer.update_tex(dmatexes, images, buffer.clone()) { buffer.rendered.store(true, Ordering::Relaxed); let material = materials.get_mut(material).unwrap(); material.base_color_texture.replace(new_tex); diff --git a/src/wayland/dmabuf/buffer_backing.rs b/src/wayland/dmabuf/buffer_backing.rs index 29f7818..9ff8e4a 100644 --- a/src/wayland/dmabuf/buffer_backing.rs +++ b/src/wayland/dmabuf/buffer_backing.rs @@ -1,50 +1,38 @@ use super::buffer_params::BufferParams; -use crate::wayland::{GraphicsInfo, Message, MessageSink, core::buffer::Buffer}; -use drm_fourcc::DrmFourcc; -use khronos_egl::{self as egl, ClientBuffer}; -use mint::Vector2; -use std::{ - os::fd::AsRawFd, - sync::{Arc, OnceLock}, +use crate::wayland::{Message, MessageSink, core::buffer::Buffer}; +use bevy::{ + asset::{Assets, Handle}, + image::Image, }; -use stereokit_rust::tex::{Tex, TexFormat, TexType}; +use bevy_dmabuf::{ + dmatex::{Dmatex, DmatexPlane, Resolution}, + import::ImportedDmatexs, +}; +use drm_fourcc::DrmFourcc; +use mint::Vector2; +use std::sync::{Arc, OnceLock}; use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags; -// EGL extension constants for DMA-BUF -const EGL_WIDTH: i32 = 0x3057; -const EGL_HEIGHT: i32 = 0x3056; -const EGL_LINUX_DRM_FOURCC_EXT: i32 = 0x3272; -const EGL_DMA_BUF_PLANE0_FD_EXT: i32 = 0x3373; -const EGL_DMA_BUF_PLANE0_OFFSET_EXT: i32 = 0x3273; -const EGL_DMA_BUF_PLANE0_PITCH_EXT: i32 = 0x3275; -const EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT: i32 = 0x3443; -const EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT: i32 = 0x3444; -const EGL_LINUX_DMA_BUF_EXT: i32 = 0x3270; -const EGL_NO_BUFFER: *mut std::ffi::c_void = std::ptr::null_mut(); - /// Parameters for a shared memory buffer #[derive(Debug)] pub struct DmabufBacking { - params: Arc, message_sink: Option, - size: Vector2, + params: Arc, + size: Vector2, format: DrmFourcc, _flags: Flags, - tex: OnceLock, + tex: OnceLock>, } impl DmabufBacking { pub fn new( params: Arc, message_sink: Option, - size: Vector2, + size: Vector2, format: DrmFourcc, flags: Flags, ) -> Self { - tracing::info!( - "Creating new DmabufBacking with BufferParams {:?}", - params.id - ); + tracing::info!("Creating new DmabufBacking",); Self { params, message_sink, @@ -55,146 +43,90 @@ impl DmabufBacking { } } - fn import_dmabuf(&self, graphics_info: &mut GraphicsInfo) -> Result { - // Sanity check for required EGL extensions - let extensions = graphics_info - .instance - .query_string(Some(graphics_info.display), egl::EXTENSIONS)?; - let extensions_str = extensions.to_string_lossy(); - let extensions_list: Vec<&str> = extensions_str.split_whitespace().collect(); - if !extensions_list.contains(&"EGL_EXT_image_dma_buf_import") { - tracing::error!("EGL extension EGL_EXT_image_dma_buf_import is not supported"); - return Err(khronos_egl::Error::BadParameter); - } - if !extensions_list.contains(&"EGL_EXT_image_dma_buf_import_modifiers") { - tracing::error!( - "EGL extension EGL_EXT_image_dma_buf_import_modifiers is not supported" - ); - return Err(khronos_egl::Error::BadParameter); - } - - let mut tex = Tex::new( - TexType::ImageNomips | TexType::Dynamic, - TexFormat::RGBA32, - nanoid::nanoid!(), - ); - - tracing::info!(format=?self.format, "Wayland: Updating DMABuf tex"); - - // Get plane info from params - let planes = self.params.lock_planes(); - let Some(plane) = planes.get(&0) else { - tracing::error!( - "Wayland: Failed to get plane 0 from BufferParams {:?}", - self.params.id - ); - return Err(khronos_egl::Error::BadParameter); + fn import_dmabuf( + &self, + dmatexes: &ImportedDmatexs, + images: &mut Assets, + buffer: Arc, + ) -> Option> { + let mut planes = std::mem::take(&mut *self.params.planes.lock()); + // TODO: AAAAAA BAD HACK WHAT THE HELL FIX THIS + let key = *planes.keys().last().unwrap(); + let plane = planes.remove(&key).unwrap(); + let dmatex = Dmatex { + dmabuf_fd: plane.fd.into(), + planes: vec![DmatexPlane { + offset: plane.offset, + stride: plane.stride as i32, + }], + res: Resolution { + x: self.size.x, + y: self.size.y, + }, + modifier: plane.modifier, + format: self.format as u32, + flip_y: self._flags.contains(Flags::YInvert), }; - tracing::info!( - "Using plane 0 with fd {} from BufferParams {:?}", - plane.fd.as_raw_fd(), - self.params.id - ); - - // Create EGL image - let image = match graphics_info.instance.create_image( - graphics_info.display, - graphics_info.context, - EGL_LINUX_DMA_BUF_EXT as u32, - unsafe { ClientBuffer::from_ptr(EGL_NO_BUFFER) }, - &[ - EGL_LINUX_DRM_FOURCC_EXT as usize, - self.format as usize, - EGL_DMA_BUF_PLANE0_FD_EXT as usize, - plane.fd.as_raw_fd() as usize, // EGL will dup() this fd internally - EGL_DMA_BUF_PLANE0_OFFSET_EXT as usize, - plane.offset as usize, - EGL_DMA_BUF_PLANE0_PITCH_EXT as usize, - plane.stride as usize, - egl::ATTRIB_NONE, - ], - ) { - Ok(image) => image, + let dmatex = dmatexes.set(images, dmatex, None); + match &dmatex { + Ok(_) => { + let _ = self + .message_sink + .as_ref() + .unwrap() + .send(Message::DmabufImportSuccess(self.params.clone(), buffer)); + } Err(e) => { - tracing::error!( - "Wayland: Failed to create EGL image. Error: {:?}, Params: size=({:?}, {:?}), format={:?}, fd={}, stride={}, offset={}", - e, - self.size.x, - self.size.y, - self.format, - plane.fd.as_raw_fd(), - plane.stride, - plane.offset - ); - return Err(e); - } - }; + tracing::error!("Failed to import dmabuf because {e}"); - // The cloned fd will be consumed by create_image, so we don't need to explicitly close it - // Create and bind GL texture - let mut gl_tex = 0; - unsafe { - gl::GenTextures(1, &mut gl_tex); - if gl_tex == 0 { - tracing::error!("Wayland: Failed to generate GL texture."); - return Err(khronos_egl::Error::BadParameter); + let _ = self + .message_sink + .as_ref() + .unwrap() + .send(Message::DmabufImportFailure(self.params.clone())); } - gl::BindTexture(gl::TEXTURE_2D, gl_tex); } - // Set the native texture handle directly - // Mesa will handle the OES texture implicitly - unsafe { - tex.set_native_surface( - gl_tex as *mut std::os::raw::c_void, - TexType::ImageNomips | TexType::Dynamic, - 0x8058, // GL_RGBA8 - self.size.x as i32, - self.size.y as i32, - 1, // single surface - true, // we own this texture - ) - }; + dmatex.ok() + } - // Clean up EGL image - if let Err(e) = graphics_info - .instance - .destroy_image(graphics_info.display, image) + pub fn update_tex( + &self, + dmatexes: &ImportedDmatexs, + images: &mut Assets, + buffer: Arc, + ) -> Option> { + if self.tex.get().is_none() + && let Some(dmatex) = self.import_dmabuf(dmatexes, images, buffer) { - tracing::error!("Wayland: Failed to destroy EGL image. Error: {:?}", e); + let _ = self.tex.set(dmatex); } - - Ok(tex) + self.tex.get().cloned() } - pub fn init_tex(&self, graphics_info: &Arc, buffer: Arc) { - if self.tex.get().is_none() { - match self.import_dmabuf(graphics_info) { - Ok(tex) => { - let _ = self.tex.set(tex); - let _ = self - .message_sink - .as_ref() - .unwrap() - .send(Message::DmabufImportSuccess(self.params.clone(), buffer)); - } - Err(e) => { - tracing::error!("Wayland: Error initializing DMABuf tex: {:?}", e); - let _ = self - .message_sink - .as_ref() - .unwrap() - .send(Message::DmabufImportFailure(self.params.clone())); - } - }; - } - } - - pub fn get_tex(&self) -> Option<&Tex> { - self.tex.get() + pub fn is_transparent(&self) -> bool { + matches!( + self.format, + DrmFourcc::Abgr1555 + | DrmFourcc::Abgr16161616f + | DrmFourcc::Abgr2101010 + | DrmFourcc::Abgr4444 + | DrmFourcc::Abgr8888 + | DrmFourcc::Argb1555 + | DrmFourcc::Argb16161616f + | DrmFourcc::Argb2101010 + | DrmFourcc::Argb4444 + | DrmFourcc::Argb8888 + | DrmFourcc::Axbxgxrx106106106106 + | DrmFourcc::Ayuv + | DrmFourcc::Rgba1010102 + | DrmFourcc::Rgba4444 + | DrmFourcc::Rgba5551 + | DrmFourcc::Rgba8888 + ) } pub fn size(&self) -> Vector2 { - self.size + [self.size.x as usize, self.size.y as usize].into() } } diff --git a/src/wayland/dmabuf/buffer_params.rs b/src/wayland/dmabuf/buffer_params.rs index 8f86ee9..59efb2c 100644 --- a/src/wayland/dmabuf/buffer_params.rs +++ b/src/wayland/dmabuf/buffer_params.rs @@ -23,7 +23,7 @@ pub struct DmabufPlane { pub fd: OwnedFd, pub offset: u32, pub stride: u32, - pub _modifier: u64, + pub modifier: u64, } /// Parameters for creating a DMA-BUF-based wl_buffer @@ -34,7 +34,7 @@ pub struct DmabufPlane { #[derive(Debug, Dispatcher)] pub struct BufferParams { pub id: ObjectId, - planes: Mutex>, + pub(super) planes: Mutex>, } impl BufferParams { @@ -45,10 +45,6 @@ impl BufferParams { planes: Mutex::new(FxHashMap::default()), } } - - pub fn lock_planes(&self) -> parking_lot::MutexGuard<'_, FxHashMap> { - self.planes.lock() - } } impl ZwpLinuxBufferParamsV1 for BufferParams { @@ -93,7 +89,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { fd, offset, stride, - _modifier: ((modifier_hi as u64) << 32) | (modifier_lo as u64), + modifier: ((modifier_hi as u64) << 32) | (modifier_lo as u64), }; // Store the plane @@ -112,7 +108,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { ) -> Result<()> { tracing::info!("Creating buffer from BufferParams {:?}", self.id); // Create the buffer with DMA-BUF backing using self as the backing - let size = [width as usize, height as usize].into(); + let size = [width as u32, height as u32].into(); let backing = DmabufBacking::new( client.get::(self.id).unwrap(), Some(client.display().message_sink.clone()), @@ -137,11 +133,10 @@ impl ZwpLinuxBufferParamsV1 for BufferParams { flags: Flags, ) -> Result<()> { // Create the buffer with DMA-BUF backing using self as the backing - let size = [width as usize, height as usize].into(); let backing = DmabufBacking::new( client.get::(self.id).unwrap(), None, - size, + [width as u32, height as u32].into(), DrmFourcc::try_from(format).unwrap(), flags, ); diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 377ab89..5d68cb7 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -1,27 +1,28 @@ pub mod core; -#[cfg(feature = "dmabuf")] pub mod dmabuf; pub mod util; pub mod xdg; +use crate::PreFrameWait; use crate::wayland::core::seat::SeatMessage; use crate::{ BevyMaterial, core::{ error::{Result, ServerError}, - graphics_info::GraphicsInfo, task, }, }; +use bevy::app::{App, Plugin, Update}; +use bevy::ecs::system::{Res, ResMut}; use bevy::{asset::Assets, ecs::resource::Resource, image::Image}; +use bevy_dmabuf::import::ImportedDmatexs; use cluFlock::ToFlock; use core::{ - buffer::{BUFFER_REGISTRY, Buffer}, + buffer::{Buffer, WL_BUFFER_REGISTRY}, callback::Callback, display::Display, surface::WL_SURFACE_REGISTRY, }; -#[cfg(feature = "dmabuf")] use dmabuf::buffer_params::BufferParams; use mint::Vector2; use std::sync::atomic::Ordering; @@ -35,7 +36,6 @@ use std::{ use tokio::{net::UnixStream, sync::mpsc, task::AbortHandle}; use tokio_stream::StreamExt; use tracing::{debug_span, instrument}; -#[cfg(feature = "dmabuf")] use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1; use waynest::{ server::{ @@ -104,9 +104,7 @@ pub fn get_free_wayland_socket_path() -> Option { pub enum Message { Frame(Arc), ReleaseBuffer(Arc), - #[cfg(feature = "dmabuf")] DmabufImportSuccess(Arc, Arc), - #[cfg(feature = "dmabuf")] DmabufImportFailure(Arc), CloseToplevel(Arc), ResizeToplevel { @@ -209,11 +207,9 @@ impl WaylandClient { client.remove(callback.0); Ok(()) } - #[cfg(feature = "dmabuf")] Message::DmabufImportSuccess(params, buffer) => { params.created(client, params.id, buffer.id).await } - #[cfg(feature = "dmabuf")] Message::DmabufImportFailure(params) => { client.remove(params.id); params.failed(client, params.id).await @@ -283,33 +279,42 @@ impl Wayland { #[allow(unreachable_code)] Ok(()) } - - pub fn early_frame(graphics_info: &mut GraphicsInfo) { - for buffer in BUFFER_REGISTRY.get_valid_contents() { - if buffer.can_release_after_update() { - if buffer.rendered.load(Ordering::Relaxed) { - let _ = buffer - .message_sink - .send(Message::ReleaseBuffer(buffer.clone())); - } - buffer.rendered.store(false, Ordering::Relaxed); - } - buffer.init_tex(graphics_info); - } - for surface in WL_SURFACE_REGISTRY.get_valid_contents() { - surface.frame_event(); - } - } - - #[instrument(level = "debug", name = "Wayland frame", skip_all)] - pub fn update_graphics(materials: &mut Assets, images: &mut Assets) { - for surface in WL_SURFACE_REGISTRY.get_valid_contents() { - surface.update_graphics(materials, images); - } - } } impl Drop for Wayland { fn drop(&mut self) { self.abort_handle.abort(); } } + +pub struct WaylandPlugin; +impl Plugin for WaylandPlugin { + fn build(&self, app: &mut App) { + app.add_systems(PreFrameWait, early_frame); + app.add_systems(Update, update_graphics); + } +} + +fn early_frame() { + for buffer in WL_BUFFER_REGISTRY.get_valid_contents() { + if buffer.rendered.load(Ordering::Relaxed) { + let _ = buffer + .message_sink + .send(Message::ReleaseBuffer(buffer.clone())); + } + buffer.rendered.store(false, Ordering::Relaxed); + } + for surface in WL_SURFACE_REGISTRY.get_valid_contents() { + surface.frame_event(); + } +} + +#[instrument(level = "debug", name = "Wayland frame", skip_all)] +fn update_graphics( + dmatexes: Res, + mut materials: ResMut>, + mut images: ResMut>, +) { + for surface in WL_SURFACE_REGISTRY.get_valid_contents() { + surface.update_graphics(&dmatexes, &mut materials, &mut images); + } +}