feat: dmatex!! (sorta, borken)
This commit is contained in:
@@ -30,7 +30,6 @@ wayland = [
|
|||||||
"dep:drm-fourcc",
|
"dep:drm-fourcc",
|
||||||
"dep:memfd",
|
"dep:memfd",
|
||||||
]
|
]
|
||||||
dmabuf = []
|
|
||||||
profile_tokio = ["dep:console-subscriber", "tokio/tracing"]
|
profile_tokio = ["dep:console-subscriber", "tokio/tracing"]
|
||||||
profile_app = ["dep:tracing-tracy", "bevy/trace_tracy", "bevy/trace"]
|
profile_app = ["dep:tracing-tracy", "bevy/trace_tracy", "bevy/trace"]
|
||||||
bevy_debugging = ["bevy/bevy_remote", "bevy/track_location"]
|
bevy_debugging = ["bevy/bevy_remote", "bevy/track_location"]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::{
|
use super::{
|
||||||
client_state::{CLIENT_STATES, ClientStateParsed},
|
client_state::{CLIENT_STATES, ClientStateParsed},
|
||||||
destroy_queue,
|
|
||||||
scenegraph::Scenegraph,
|
scenegraph::Scenegraph,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -231,9 +230,6 @@ impl Client {
|
|||||||
if let Some(flush_join_handle) = self.flush_join_handle.get() {
|
if let Some(flush_join_handle) = self.flush_join_handle.get() {
|
||||||
flush_join_handle.abort();
|
flush_join_handle.abort();
|
||||||
}
|
}
|
||||||
if let Some(client) = CLIENTS.remove(self) {
|
|
||||||
destroy_queue::add(client);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Debug for Client {
|
impl Debug for Client {
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
use parking_lot::Mutex;
|
|
||||||
use std::{any::Any, sync::LazyLock};
|
|
||||||
use tokio::sync::mpsc::{self, unbounded_channel};
|
|
||||||
|
|
||||||
type Anything = Box<dyn Any + Send + Sync>;
|
|
||||||
|
|
||||||
static MAIN_DESTROY_QUEUE: LazyLock<(
|
|
||||||
mpsc::UnboundedSender<Anything>,
|
|
||||||
Mutex<mpsc::UnboundedReceiver<Anything>>,
|
|
||||||
)> = LazyLock::new(|| {
|
|
||||||
let (tx, rx) = unbounded_channel();
|
|
||||||
(tx, Mutex::new(rx))
|
|
||||||
});
|
|
||||||
|
|
||||||
pub fn add<T: Any + Sync + Send>(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<Image>>,
|
|
||||||
}
|
|
||||||
@@ -3,10 +3,8 @@ pub mod client;
|
|||||||
pub mod client_state;
|
pub mod client_state;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
pub mod delta;
|
pub mod delta;
|
||||||
pub mod destroy_queue;
|
|
||||||
pub mod entity_handle;
|
pub mod entity_handle;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod graphics_info;
|
|
||||||
pub mod registry;
|
pub mod registry;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
pub mod scenegraph;
|
pub mod scenegraph;
|
||||||
|
|||||||
13
src/main.rs
13
src/main.rs
@@ -8,7 +8,6 @@ mod session;
|
|||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
mod wayland;
|
mod wayland;
|
||||||
|
|
||||||
use crate::core::destroy_queue;
|
|
||||||
use crate::nodes::input;
|
use crate::nodes::input;
|
||||||
|
|
||||||
use bevy::MinimalPlugins;
|
use bevy::MinimalPlugins;
|
||||||
@@ -46,7 +45,6 @@ use bevy_mod_xr::session::{XrFirst, XrHandleEvents, XrSessionPlugin};
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use core::client::{Client, tick_internal_client};
|
use core::client::{Client, tick_internal_client};
|
||||||
use core::entity_handle::EntityHandlePlugin;
|
use core::entity_handle::EntityHandlePlugin;
|
||||||
use core::graphics_info::GraphicsInfo;
|
|
||||||
use core::task;
|
use core::task;
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
use nodes::audio::AudioNodePlugin;
|
use nodes::audio::AudioNodePlugin;
|
||||||
@@ -449,13 +447,6 @@ fn add_oit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn xr_step(world: &mut World) {
|
fn xr_step(world: &mut World) {
|
||||||
// camera::update(token);
|
|
||||||
#[cfg(feature = "wayland")]
|
|
||||||
Wayland::early_frame(&mut GraphicsInfo {
|
|
||||||
_images: world.resource_mut::<Assets<Image>>(),
|
|
||||||
});
|
|
||||||
destroy_queue::clear();
|
|
||||||
|
|
||||||
// update things like the Xr input methods
|
// update things like the Xr input methods
|
||||||
world.run_schedule(PreFrameWait);
|
world.run_schedule(PreFrameWait);
|
||||||
input::process_input();
|
input::process_input();
|
||||||
@@ -487,8 +478,4 @@ fn xr_step(world: &mut World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tick_internal_client();
|
tick_internal_client();
|
||||||
#[cfg(feature = "wayland")]
|
|
||||||
world.resource_scope::<Assets<BevyMaterial>, _>(|world, mut materials| {
|
|
||||||
Wayland::update_graphics(&mut materials, &mut world.resource_mut::<Assets<Image>>());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
use std::sync::{Arc, atomic::AtomicBool};
|
use std::sync::{Arc, atomic::AtomicBool};
|
||||||
|
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
use crate::wayland::dmabuf::buffer_backing::DmabufBacking;
|
use crate::wayland::dmabuf::buffer_backing::DmabufBacking;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::registry::Registry,
|
core::registry::Registry,
|
||||||
wayland::{
|
wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt},
|
||||||
GraphicsInfo, MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{Assets, Handle},
|
asset::{Assets, Handle},
|
||||||
image::Image,
|
image::Image,
|
||||||
};
|
};
|
||||||
|
use bevy_dmabuf::import::ImportedDmatexs;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
pub use waynest::server::protocol::core::wayland::wl_buffer::*;
|
pub use waynest::server::protocol::core::wayland::wl_buffer::*;
|
||||||
use waynest::{
|
use waynest::{
|
||||||
@@ -19,12 +17,11 @@ use waynest::{
|
|||||||
wire::ObjectId,
|
wire::ObjectId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static BUFFER_REGISTRY: Registry<Buffer> = Registry::new();
|
pub static WL_BUFFER_REGISTRY: Registry<Buffer> = Registry::new();
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BufferBacking {
|
pub enum BufferBacking {
|
||||||
Shm(ShmBufferBacking),
|
Shm(ShmBufferBacking),
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
Dmabuf(DmabufBacking),
|
Dmabuf(DmabufBacking),
|
||||||
}
|
}
|
||||||
impl BufferBacking {
|
impl BufferBacking {
|
||||||
@@ -53,29 +50,21 @@ impl Buffer {
|
|||||||
rendered: AtomicBool::new(false),
|
rendered: AtomicBool::new(false),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
BUFFER_REGISTRY.add_raw(&buffer);
|
WL_BUFFER_REGISTRY.add_raw(&buffer);
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn init_tex(self: Arc<Self>, 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
|
/// Returns the tex if it was updated
|
||||||
pub fn update_tex(&self, images: &mut Assets<Image>) -> Option<Handle<Image>> {
|
pub fn update_tex(
|
||||||
|
&self,
|
||||||
|
dmatexes: &ImportedDmatexs,
|
||||||
|
images: &mut Assets<Image>,
|
||||||
|
buffer: Arc<Buffer>,
|
||||||
|
) -> Option<Handle<Image>> {
|
||||||
tracing::debug!("Updating texture for buffer {:?}", self.id);
|
tracing::debug!("Updating texture for buffer {:?}", self.id);
|
||||||
match &self.backing {
|
match &self.backing {
|
||||||
BufferBacking::Shm(backing) => backing.update_tex(images),
|
BufferBacking::Shm(backing) => backing.update_tex(images),
|
||||||
#[cfg(feature = "dmabuf")]
|
BufferBacking::Dmabuf(backing) => backing.update_tex(dmatexes, images, buffer),
|
||||||
BufferBacking::Dmabuf(backing) => backing
|
|
||||||
.get_tex()
|
|
||||||
.map(|tex| tex.get_id().to_string())
|
|
||||||
.and_then(|tex_id| Tex::find(tex_id).ok()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +75,6 @@ impl Buffer {
|
|||||||
pub fn is_transparent(&self) -> bool {
|
pub fn is_transparent(&self) -> bool {
|
||||||
match &self.backing {
|
match &self.backing {
|
||||||
BufferBacking::Shm(backing) => backing.is_transparent(),
|
BufferBacking::Shm(backing) => backing.is_transparent(),
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
BufferBacking::Dmabuf(backing) => backing.is_transparent(),
|
BufferBacking::Dmabuf(backing) => backing.is_transparent(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +82,6 @@ impl Buffer {
|
|||||||
pub fn size(&self) -> Vector2<usize> {
|
pub fn size(&self) -> Vector2<usize> {
|
||||||
match &self.backing {
|
match &self.backing {
|
||||||
BufferBacking::Shm(backing) => backing.size(),
|
BufferBacking::Shm(backing) => backing.size(),
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
BufferBacking::Dmabuf(backing) => backing.size(),
|
BufferBacking::Dmabuf(backing) => backing.size(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ use crate::wayland::{
|
|||||||
seat::{Seat, WlSeat},
|
seat::{Seat, WlSeat},
|
||||||
shm::{Shm, WlShm},
|
shm::{Shm, WlShm},
|
||||||
},
|
},
|
||||||
|
dmabuf::Dmabuf,
|
||||||
xdg::wm_base::{WmBase, XdgWmBase},
|
xdg::wm_base::{WmBase, XdgWmBase},
|
||||||
};
|
};
|
||||||
pub use waynest::server::protocol::core::wayland::wl_registry::*;
|
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::protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1;
|
||||||
use waynest::{
|
use waynest::{
|
||||||
server::{Client, Dispatcher, Error, Result},
|
server::{Client, Dispatcher, Error, Result},
|
||||||
@@ -23,7 +24,6 @@ impl RegistryGlobals {
|
|||||||
pub const WM_BASE: u32 = 2;
|
pub const WM_BASE: u32 = 2;
|
||||||
pub const SEAT: u32 = 3;
|
pub const SEAT: u32 = 3;
|
||||||
pub const OUTPUT: u32 = 4;
|
pub const OUTPUT: u32 = 4;
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
pub const DMABUF: u32 = 5;
|
pub const DMABUF: u32 = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,6 @@ impl Registry {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
self.global(
|
self.global(
|
||||||
client,
|
client,
|
||||||
sender_id,
|
sender_id,
|
||||||
@@ -131,7 +130,6 @@ impl WlRegistry for Registry {
|
|||||||
tracing::info!("Binding output");
|
tracing::info!("Binding output");
|
||||||
client.insert(new_id.object_id, Output);
|
client.insert(new_id.object_id, Output);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
RegistryGlobals::DMABUF => {
|
RegistryGlobals::DMABUF => {
|
||||||
tracing::info!("Binding dmabuf");
|
tracing::info!("Binding dmabuf");
|
||||||
let dmabuf = client.insert(new_id.object_id, Dmabuf::new());
|
let dmabuf = client.insert(new_id.object_id, Dmabuf::new());
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use bevy::{
|
|||||||
image::Image,
|
image::Image,
|
||||||
render::alpha::AlphaMode,
|
render::alpha::AlphaMode,
|
||||||
};
|
};
|
||||||
|
use bevy_dmabuf::import::ImportedDmatexs;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::{Arc, OnceLock, atomic::Ordering};
|
use std::sync::{Arc, OnceLock, atomic::Ordering};
|
||||||
@@ -111,6 +112,7 @@ impl Surface {
|
|||||||
|
|
||||||
pub fn update_graphics(
|
pub fn update_graphics(
|
||||||
&self,
|
&self,
|
||||||
|
dmatexes: &ImportedDmatexs,
|
||||||
materials: &mut Assets<BevyMaterial>,
|
materials: &mut Assets<BevyMaterial>,
|
||||||
images: &mut Assets<Image>,
|
images: &mut Assets<Image>,
|
||||||
) {
|
) {
|
||||||
@@ -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);
|
buffer.rendered.store(true, Ordering::Relaxed);
|
||||||
let material = materials.get_mut(material).unwrap();
|
let material = materials.get_mut(material).unwrap();
|
||||||
material.base_color_texture.replace(new_tex);
|
material.base_color_texture.replace(new_tex);
|
||||||
|
|||||||
@@ -1,50 +1,38 @@
|
|||||||
use super::buffer_params::BufferParams;
|
use super::buffer_params::BufferParams;
|
||||||
use crate::wayland::{GraphicsInfo, Message, MessageSink, core::buffer::Buffer};
|
use crate::wayland::{Message, MessageSink, core::buffer::Buffer};
|
||||||
use drm_fourcc::DrmFourcc;
|
use bevy::{
|
||||||
use khronos_egl::{self as egl, ClientBuffer};
|
asset::{Assets, Handle},
|
||||||
use mint::Vector2;
|
image::Image,
|
||||||
use std::{
|
|
||||||
os::fd::AsRawFd,
|
|
||||||
sync::{Arc, OnceLock},
|
|
||||||
};
|
};
|
||||||
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;
|
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
|
/// Parameters for a shared memory buffer
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DmabufBacking {
|
pub struct DmabufBacking {
|
||||||
params: Arc<BufferParams>,
|
|
||||||
message_sink: Option<MessageSink>,
|
message_sink: Option<MessageSink>,
|
||||||
size: Vector2<usize>,
|
params: Arc<BufferParams>,
|
||||||
|
size: Vector2<u32>,
|
||||||
format: DrmFourcc,
|
format: DrmFourcc,
|
||||||
_flags: Flags,
|
_flags: Flags,
|
||||||
tex: OnceLock<Tex>,
|
tex: OnceLock<Handle<Image>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DmabufBacking {
|
impl DmabufBacking {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
params: Arc<BufferParams>,
|
params: Arc<BufferParams>,
|
||||||
message_sink: Option<MessageSink>,
|
message_sink: Option<MessageSink>,
|
||||||
size: Vector2<usize>,
|
size: Vector2<u32>,
|
||||||
format: DrmFourcc,
|
format: DrmFourcc,
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
tracing::info!(
|
tracing::info!("Creating new DmabufBacking",);
|
||||||
"Creating new DmabufBacking with BufferParams {:?}",
|
|
||||||
params.id
|
|
||||||
);
|
|
||||||
Self {
|
Self {
|
||||||
params,
|
params,
|
||||||
message_sink,
|
message_sink,
|
||||||
@@ -55,146 +43,90 @@ impl DmabufBacking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_dmabuf(&self, graphics_info: &mut GraphicsInfo) -> Result<Tex, khronos_egl::Error> {
|
fn import_dmabuf(
|
||||||
// Sanity check for required EGL extensions
|
&self,
|
||||||
let extensions = graphics_info
|
dmatexes: &ImportedDmatexs,
|
||||||
.instance
|
images: &mut Assets<Image>,
|
||||||
.query_string(Some(graphics_info.display), egl::EXTENSIONS)?;
|
buffer: Arc<Buffer>,
|
||||||
let extensions_str = extensions.to_string_lossy();
|
) -> Option<Handle<Image>> {
|
||||||
let extensions_list: Vec<&str> = extensions_str.split_whitespace().collect();
|
let mut planes = std::mem::take(&mut *self.params.planes.lock());
|
||||||
if !extensions_list.contains(&"EGL_EXT_image_dma_buf_import") {
|
// TODO: AAAAAA BAD HACK WHAT THE HELL FIX THIS
|
||||||
tracing::error!("EGL extension EGL_EXT_image_dma_buf_import is not supported");
|
let key = *planes.keys().last().unwrap();
|
||||||
return Err(khronos_egl::Error::BadParameter);
|
let plane = planes.remove(&key).unwrap();
|
||||||
}
|
let dmatex = Dmatex {
|
||||||
if !extensions_list.contains(&"EGL_EXT_image_dma_buf_import_modifiers") {
|
dmabuf_fd: plane.fd.into(),
|
||||||
tracing::error!(
|
planes: vec![DmatexPlane {
|
||||||
"EGL extension EGL_EXT_image_dma_buf_import_modifiers is not supported"
|
offset: plane.offset,
|
||||||
);
|
stride: plane.stride as i32,
|
||||||
return Err(khronos_egl::Error::BadParameter);
|
}],
|
||||||
}
|
res: Resolution {
|
||||||
|
x: self.size.x,
|
||||||
let mut tex = Tex::new(
|
y: self.size.y,
|
||||||
TexType::ImageNomips | TexType::Dynamic,
|
},
|
||||||
TexFormat::RGBA32,
|
modifier: plane.modifier,
|
||||||
nanoid::nanoid!(),
|
format: self.format as u32,
|
||||||
);
|
flip_y: self._flags.contains(Flags::YInvert),
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
tracing::info!(
|
let dmatex = dmatexes.set(images, dmatex, None);
|
||||||
"Using plane 0 with fd {} from BufferParams {:?}",
|
match &dmatex {
|
||||||
plane.fd.as_raw_fd(),
|
Ok(_) => {
|
||||||
self.params.id
|
let _ = self
|
||||||
);
|
.message_sink
|
||||||
|
.as_ref()
|
||||||
// Create EGL image
|
.unwrap()
|
||||||
let image = match graphics_info.instance.create_image(
|
.send(Message::DmabufImportSuccess(self.params.clone(), buffer));
|
||||||
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,
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!(
|
tracing::error!("Failed to import dmabuf because {e}");
|
||||||
"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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The cloned fd will be consumed by create_image, so we don't need to explicitly close it
|
let _ = self
|
||||||
// Create and bind GL texture
|
.message_sink
|
||||||
let mut gl_tex = 0;
|
.as_ref()
|
||||||
unsafe {
|
.unwrap()
|
||||||
gl::GenTextures(1, &mut gl_tex);
|
.send(Message::DmabufImportFailure(self.params.clone()));
|
||||||
if gl_tex == 0 {
|
|
||||||
tracing::error!("Wayland: Failed to generate GL texture.");
|
|
||||||
return Err(khronos_egl::Error::BadParameter);
|
|
||||||
}
|
}
|
||||||
gl::BindTexture(gl::TEXTURE_2D, gl_tex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the native texture handle directly
|
dmatex.ok()
|
||||||
// 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
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clean up EGL image
|
pub fn update_tex(
|
||||||
if let Err(e) = graphics_info
|
&self,
|
||||||
.instance
|
dmatexes: &ImportedDmatexs,
|
||||||
.destroy_image(graphics_info.display, image)
|
images: &mut Assets<Image>,
|
||||||
|
buffer: Arc<Buffer>,
|
||||||
|
) -> Option<Handle<Image>> {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
self.tex.get().cloned()
|
||||||
Ok(tex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_tex(&self, graphics_info: &Arc<GraphicsInfo>, buffer: Arc<Buffer>) {
|
pub fn is_transparent(&self) -> bool {
|
||||||
if self.tex.get().is_none() {
|
matches!(
|
||||||
match self.import_dmabuf(graphics_info) {
|
self.format,
|
||||||
Ok(tex) => {
|
DrmFourcc::Abgr1555
|
||||||
let _ = self.tex.set(tex);
|
| DrmFourcc::Abgr16161616f
|
||||||
let _ = self
|
| DrmFourcc::Abgr2101010
|
||||||
.message_sink
|
| DrmFourcc::Abgr4444
|
||||||
.as_ref()
|
| DrmFourcc::Abgr8888
|
||||||
.unwrap()
|
| DrmFourcc::Argb1555
|
||||||
.send(Message::DmabufImportSuccess(self.params.clone(), buffer));
|
| DrmFourcc::Argb16161616f
|
||||||
}
|
| DrmFourcc::Argb2101010
|
||||||
Err(e) => {
|
| DrmFourcc::Argb4444
|
||||||
tracing::error!("Wayland: Error initializing DMABuf tex: {:?}", e);
|
| DrmFourcc::Argb8888
|
||||||
let _ = self
|
| DrmFourcc::Axbxgxrx106106106106
|
||||||
.message_sink
|
| DrmFourcc::Ayuv
|
||||||
.as_ref()
|
| DrmFourcc::Rgba1010102
|
||||||
.unwrap()
|
| DrmFourcc::Rgba4444
|
||||||
.send(Message::DmabufImportFailure(self.params.clone()));
|
| DrmFourcc::Rgba5551
|
||||||
}
|
| DrmFourcc::Rgba8888
|
||||||
};
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_tex(&self) -> Option<&Tex> {
|
|
||||||
self.tex.get()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> Vector2<usize> {
|
pub fn size(&self) -> Vector2<usize> {
|
||||||
self.size
|
[self.size.x as usize, self.size.y as usize].into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub struct DmabufPlane {
|
|||||||
pub fd: OwnedFd,
|
pub fd: OwnedFd,
|
||||||
pub offset: u32,
|
pub offset: u32,
|
||||||
pub stride: u32,
|
pub stride: u32,
|
||||||
pub _modifier: u64,
|
pub modifier: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameters for creating a DMA-BUF-based wl_buffer
|
/// Parameters for creating a DMA-BUF-based wl_buffer
|
||||||
@@ -34,7 +34,7 @@ pub struct DmabufPlane {
|
|||||||
#[derive(Debug, Dispatcher)]
|
#[derive(Debug, Dispatcher)]
|
||||||
pub struct BufferParams {
|
pub struct BufferParams {
|
||||||
pub id: ObjectId,
|
pub id: ObjectId,
|
||||||
planes: Mutex<FxHashMap<u32, DmabufPlane>>,
|
pub(super) planes: Mutex<FxHashMap<u32, DmabufPlane>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufferParams {
|
impl BufferParams {
|
||||||
@@ -45,10 +45,6 @@ impl BufferParams {
|
|||||||
planes: Mutex::new(FxHashMap::default()),
|
planes: Mutex::new(FxHashMap::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_planes(&self) -> parking_lot::MutexGuard<'_, FxHashMap<u32, DmabufPlane>> {
|
|
||||||
self.planes.lock()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZwpLinuxBufferParamsV1 for BufferParams {
|
impl ZwpLinuxBufferParamsV1 for BufferParams {
|
||||||
@@ -93,7 +89,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
|
|||||||
fd,
|
fd,
|
||||||
offset,
|
offset,
|
||||||
stride,
|
stride,
|
||||||
_modifier: ((modifier_hi as u64) << 32) | (modifier_lo as u64),
|
modifier: ((modifier_hi as u64) << 32) | (modifier_lo as u64),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store the plane
|
// Store the plane
|
||||||
@@ -112,7 +108,7 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
tracing::info!("Creating buffer from BufferParams {:?}", self.id);
|
tracing::info!("Creating buffer from BufferParams {:?}", self.id);
|
||||||
// Create the buffer with DMA-BUF backing using self as the backing
|
// 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(
|
let backing = DmabufBacking::new(
|
||||||
client.get::<Self>(self.id).unwrap(),
|
client.get::<Self>(self.id).unwrap(),
|
||||||
Some(client.display().message_sink.clone()),
|
Some(client.display().message_sink.clone()),
|
||||||
@@ -137,11 +133,10 @@ impl ZwpLinuxBufferParamsV1 for BufferParams {
|
|||||||
flags: Flags,
|
flags: Flags,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Create the buffer with DMA-BUF backing using self as the backing
|
// 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(
|
let backing = DmabufBacking::new(
|
||||||
client.get::<Self>(self.id).unwrap(),
|
client.get::<Self>(self.id).unwrap(),
|
||||||
None,
|
None,
|
||||||
size,
|
[width as u32, height as u32].into(),
|
||||||
DrmFourcc::try_from(format).unwrap(),
|
DrmFourcc::try_from(format).unwrap(),
|
||||||
flags,
|
flags,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
pub mod dmabuf;
|
pub mod dmabuf;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod xdg;
|
pub mod xdg;
|
||||||
|
|
||||||
|
use crate::PreFrameWait;
|
||||||
use crate::wayland::core::seat::SeatMessage;
|
use crate::wayland::core::seat::SeatMessage;
|
||||||
use crate::{
|
use crate::{
|
||||||
BevyMaterial,
|
BevyMaterial,
|
||||||
core::{
|
core::{
|
||||||
error::{Result, ServerError},
|
error::{Result, ServerError},
|
||||||
graphics_info::GraphicsInfo,
|
|
||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use bevy::app::{App, Plugin, Update};
|
||||||
|
use bevy::ecs::system::{Res, ResMut};
|
||||||
use bevy::{asset::Assets, ecs::resource::Resource, image::Image};
|
use bevy::{asset::Assets, ecs::resource::Resource, image::Image};
|
||||||
|
use bevy_dmabuf::import::ImportedDmatexs;
|
||||||
use cluFlock::ToFlock;
|
use cluFlock::ToFlock;
|
||||||
use core::{
|
use core::{
|
||||||
buffer::{BUFFER_REGISTRY, Buffer},
|
buffer::{Buffer, WL_BUFFER_REGISTRY},
|
||||||
callback::Callback,
|
callback::Callback,
|
||||||
display::Display,
|
display::Display,
|
||||||
surface::WL_SURFACE_REGISTRY,
|
surface::WL_SURFACE_REGISTRY,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
use dmabuf::buffer_params::BufferParams;
|
use dmabuf::buffer_params::BufferParams;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
@@ -35,7 +36,6 @@ use std::{
|
|||||||
use tokio::{net::UnixStream, sync::mpsc, task::AbortHandle};
|
use tokio::{net::UnixStream, sync::mpsc, task::AbortHandle};
|
||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
use tracing::{debug_span, instrument};
|
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::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1;
|
||||||
use waynest::{
|
use waynest::{
|
||||||
server::{
|
server::{
|
||||||
@@ -104,9 +104,7 @@ pub fn get_free_wayland_socket_path() -> Option<PathBuf> {
|
|||||||
pub enum Message {
|
pub enum Message {
|
||||||
Frame(Arc<Callback>),
|
Frame(Arc<Callback>),
|
||||||
ReleaseBuffer(Arc<Buffer>),
|
ReleaseBuffer(Arc<Buffer>),
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
DmabufImportSuccess(Arc<BufferParams>, Arc<Buffer>),
|
DmabufImportSuccess(Arc<BufferParams>, Arc<Buffer>),
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
DmabufImportFailure(Arc<BufferParams>),
|
DmabufImportFailure(Arc<BufferParams>),
|
||||||
CloseToplevel(Arc<Toplevel>),
|
CloseToplevel(Arc<Toplevel>),
|
||||||
ResizeToplevel {
|
ResizeToplevel {
|
||||||
@@ -209,11 +207,9 @@ impl WaylandClient {
|
|||||||
client.remove(callback.0);
|
client.remove(callback.0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
Message::DmabufImportSuccess(params, buffer) => {
|
Message::DmabufImportSuccess(params, buffer) => {
|
||||||
params.created(client, params.id, buffer.id).await
|
params.created(client, params.id, buffer.id).await
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dmabuf")]
|
|
||||||
Message::DmabufImportFailure(params) => {
|
Message::DmabufImportFailure(params) => {
|
||||||
client.remove(params.id);
|
client.remove(params.id);
|
||||||
params.failed(client, params.id).await
|
params.failed(client, params.id).await
|
||||||
@@ -283,33 +279,42 @@ impl Wayland {
|
|||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
Ok(())
|
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<BevyMaterial>, images: &mut Assets<Image>) {
|
|
||||||
for surface in WL_SURFACE_REGISTRY.get_valid_contents() {
|
|
||||||
surface.update_graphics(materials, images);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl Drop for Wayland {
|
impl Drop for Wayland {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.abort_handle.abort();
|
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<ImportedDmatexs>,
|
||||||
|
mut materials: ResMut<Assets<BevyMaterial>>,
|
||||||
|
mut images: ResMut<Assets<Image>>,
|
||||||
|
) {
|
||||||
|
for surface in WL_SURFACE_REGISTRY.get_valid_contents() {
|
||||||
|
surface.update_graphics(&dmatexes, &mut materials, &mut images);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user