fix(wayland): support all dmabuf protocol versions
This commit is contained in:
@@ -133,8 +133,9 @@ impl WlRegistry for Registry {
|
|||||||
}
|
}
|
||||||
RegistryGlobals::DMABUF => {
|
RegistryGlobals::DMABUF => {
|
||||||
tracing::info!("Binding dmabuf");
|
tracing::info!("Binding dmabuf");
|
||||||
let dmabuf = client.insert(new_id.object_id, Dmabuf::new());
|
|
||||||
dmabuf.send_modifiers(client, new_id.object_id).await?;
|
let dmabuf = Dmabuf::new(client, new_id.object_id, new_id.version).await?;
|
||||||
|
client.insert(new_id.object_id, dmabuf);
|
||||||
}
|
}
|
||||||
id => {
|
id => {
|
||||||
tracing::error!(id, "Wayland: failed to bind to registry global");
|
tracing::error!(id, "Wayland: failed to bind to registry global");
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
use bevy_dmabuf::{
|
use super::Dmabuf;
|
||||||
format_mapping::{drm_fourcc_to_vk_format, vk_format_to_drm_fourcc},
|
use crate::wayland::vulkano_data::VULKANO_CONTEXT;
|
||||||
wgpu_init::vulkan_to_wgpu,
|
|
||||||
};
|
|
||||||
use drm_fourcc::DrmFourcc;
|
use drm_fourcc::DrmFourcc;
|
||||||
use memfd::MemfdOptions;
|
use memfd::MemfdOptions;
|
||||||
use std::{
|
use std::{
|
||||||
io::Write,
|
io::Write,
|
||||||
os::fd::{FromRawFd, IntoRawFd, OwnedFd},
|
os::fd::{FromRawFd, IntoRawFd, OwnedFd},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use waynest::{
|
use waynest::{
|
||||||
server::{
|
server::{
|
||||||
@@ -18,42 +17,17 @@ use waynest::{
|
|||||||
wire::ObjectId,
|
wire::ObjectId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::wayland::vulkano_data::{DMA_CAPABLE_FORMATS, VULKANO_CONTEXT};
|
|
||||||
|
|
||||||
#[derive(Debug, Dispatcher)]
|
#[derive(Debug, Dispatcher)]
|
||||||
pub struct DmabufFeedback;
|
pub struct DmabufFeedback(pub Arc<Dmabuf>);
|
||||||
impl DmabufFeedback {
|
impl DmabufFeedback {
|
||||||
pub async fn send_params(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> {
|
pub async fn send_params(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> {
|
||||||
let vk = VULKANO_CONTEXT.wait();
|
let num_formats = self.0.formats.len();
|
||||||
let formats = DMA_CAPABLE_FORMATS
|
|
||||||
.iter()
|
|
||||||
.filter(|f| {
|
|
||||||
vk_format_to_drm_fourcc((**f).into())
|
|
||||||
.and_then(drm_fourcc_to_vk_format)
|
|
||||||
.and_then(vulkan_to_wgpu)
|
|
||||||
.is_some()
|
|
||||||
})
|
|
||||||
.filter_map(|f| {
|
|
||||||
Some((
|
|
||||||
vk_format_to_drm_fourcc((*f).into())?,
|
|
||||||
vk.phys_dev
|
|
||||||
.format_properties(*f)
|
|
||||||
.ok()?
|
|
||||||
.drm_format_modifier_properties
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| v.drm_format_modifier)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.flat_map(|(f, mods)| mods.into_iter().map(move |modifier| (f, modifier)))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let num_formats = formats.len();
|
|
||||||
// Send format table first
|
// Send format table first
|
||||||
self.send_format_table(client, sender_id, formats).await?;
|
self.send_format_table(client, sender_id, &self.0.formats)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Get the device information from Vulkan properties
|
// Get the device information from Vulkan properties
|
||||||
let props = vk.phys_dev.properties();
|
let props = VULKANO_CONTEXT.get().unwrap().phys_dev.properties();
|
||||||
|
|
||||||
// Create dev_t from the primary node major/minor numbers
|
// Create dev_t from the primary node major/minor numbers
|
||||||
let primary_dev_id = {
|
let primary_dev_id = {
|
||||||
@@ -92,7 +66,7 @@ impl DmabufFeedback {
|
|||||||
&self,
|
&self,
|
||||||
client: &mut Client,
|
client: &mut Client,
|
||||||
sender_id: ObjectId,
|
sender_id: ObjectId,
|
||||||
formats: Vec<(DrmFourcc, u64)>,
|
formats: &[(DrmFourcc, u64)],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Format + modifier pair (16 bytes):
|
// Format + modifier pair (16 bytes):
|
||||||
// - format: u32
|
// - format: u32
|
||||||
@@ -107,7 +81,7 @@ impl DmabufFeedback {
|
|||||||
mfd.as_file().set_len(size as u64)?;
|
mfd.as_file().set_len(size as u64)?;
|
||||||
|
|
||||||
for (format, modifier) in formats {
|
for (format, modifier) in formats {
|
||||||
let format = format as u32;
|
let format = format.clone() as u32;
|
||||||
// Write the format+modifier pair
|
// Write the format+modifier pair
|
||||||
mfd.as_file().write_all(&format.to_ne_bytes())?;
|
mfd.as_file().write_all(&format.to_ne_bytes())?;
|
||||||
mfd.as_file().write_all(&0_u32.to_ne_bytes())?;
|
mfd.as_file().write_all(&0_u32.to_ne_bytes())?;
|
||||||
|
|||||||
@@ -2,19 +2,31 @@ pub mod buffer_backing;
|
|||||||
pub mod buffer_params;
|
pub mod buffer_params;
|
||||||
pub mod feedback;
|
pub mod feedback;
|
||||||
|
|
||||||
|
use bevy_dmabuf::{
|
||||||
|
format_mapping::{drm_fourcc_to_vk_format, vk_format_to_drm_fourcc},
|
||||||
|
wgpu_init::vulkan_to_wgpu,
|
||||||
|
};
|
||||||
use buffer_params::BufferParams;
|
use buffer_params::BufferParams;
|
||||||
use drm_fourcc::DrmFourcc;
|
use drm_fourcc::DrmFourcc;
|
||||||
use feedback::DmabufFeedback;
|
use feedback::DmabufFeedback;
|
||||||
use waynest::{
|
use waynest::{
|
||||||
server::{
|
server::{
|
||||||
Client, Dispatcher, Result,
|
Client, Dispatcher, Error, Result,
|
||||||
protocol::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
protocol::{
|
||||||
|
core::wayland::wl_display::WlDisplay,
|
||||||
|
stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wire::ObjectId,
|
wire::ObjectId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
util::ClientExt,
|
||||||
|
vulkano_data::{DMA_CAPABLE_FORMATS, VULKANO_CONTEXT},
|
||||||
|
};
|
||||||
|
|
||||||
/// Main DMA-BUF interface implementation
|
/// Main DMA-BUF interface implementation
|
||||||
///
|
///
|
||||||
/// This interface allows clients to create wl_buffers from DMA-BUFs.
|
/// This interface allows clients to create wl_buffers from DMA-BUFs.
|
||||||
@@ -27,32 +39,68 @@ use crate::core::registry::Registry;
|
|||||||
/// - Coherency for read access in dmabuf data
|
/// - Coherency for read access in dmabuf data
|
||||||
/// - Proper lifetime management of dmabuf file descriptors
|
/// - Proper lifetime management of dmabuf file descriptors
|
||||||
/// - Safe handling of buffer attachments
|
/// - Safe handling of buffer attachments
|
||||||
#[derive(Dispatcher)]
|
#[derive(Debug, Dispatcher)]
|
||||||
pub struct Dmabuf {
|
pub struct Dmabuf {
|
||||||
// Track supported formats and modifiers
|
// Track supported formats and modifiers
|
||||||
// formats: Mutex<FxHashSet<DrmFormat>>,
|
// formats: Mutex<FxHashSet<DrmFormat>>,
|
||||||
// Track active buffer parameters objects by their ID
|
// Track active buffer parameters objects by their ID
|
||||||
active_params: Registry<BufferParams>,
|
active_params: Registry<BufferParams>,
|
||||||
|
pub(self) version: u32,
|
||||||
|
pub(self) formats: Vec<(DrmFourcc, u64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dmabuf {
|
impl Dmabuf {
|
||||||
/// Create a new DMA-BUF interface instance
|
/// Create a new DMA-BUF interface instance
|
||||||
pub fn new() -> Self {
|
pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> Result<Self> {
|
||||||
// let mut formats = FxHashSet::default();
|
let vk = VULKANO_CONTEXT.wait();
|
||||||
|
let formats = DMA_CAPABLE_FORMATS
|
||||||
|
.iter()
|
||||||
|
.filter(|f| {
|
||||||
|
vk_format_to_drm_fourcc((**f).into())
|
||||||
|
.and_then(drm_fourcc_to_vk_format)
|
||||||
|
.and_then(vulkan_to_wgpu)
|
||||||
|
.is_some()
|
||||||
|
})
|
||||||
|
.filter_map(|f| {
|
||||||
|
Some((
|
||||||
|
vk_format_to_drm_fourcc((*f).into())?,
|
||||||
|
vk.phys_dev
|
||||||
|
.format_properties(*f)
|
||||||
|
.ok()?
|
||||||
|
.drm_format_modifier_properties
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| v.drm_format_modifier)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.flat_map(|(f, mods)| mods.into_iter().map(move |modifier| (f, modifier)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
Self {
|
let dmabuf = Self {
|
||||||
// formats: Mutex::new(formats),
|
// formats: Mutex::new(formats),
|
||||||
active_params: Registry::new(),
|
active_params: Registry::new(),
|
||||||
}
|
version,
|
||||||
}
|
formats,
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn send_modifiers(&self, client: &mut Client, sender_id: ObjectId) -> Result<()> {
|
if version > 3 {
|
||||||
let format = DrmFourcc::Xrgb8888 as u32;
|
for (format, _) in &dmabuf.formats {
|
||||||
let modifier_hi = 0u32; // Linear modifier high 32 bits
|
dmabuf.format(client, id, *format as u32).await?;
|
||||||
let modifier_lo = 0u32; // Linear modifier low 32 bits
|
}
|
||||||
self.modifier(client, sender_id, format, modifier_hi, modifier_lo)
|
}
|
||||||
.await?;
|
// `modifier` is deprecated in version 4
|
||||||
Ok(())
|
if version == 3 {
|
||||||
|
for (format, modifier) in &dmabuf.formats {
|
||||||
|
let format = *format as u32;
|
||||||
|
let modifier_hi = (*modifier >> 32) as u32;
|
||||||
|
let modifier_lo = *modifier as u32;
|
||||||
|
dmabuf
|
||||||
|
.modifier(client, id, format, modifier_hi, modifier_lo)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(dmabuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a buffer parameters object from tracking
|
/// Remove a buffer parameters object from tracking
|
||||||
@@ -82,11 +130,24 @@ impl ZwpLinuxDmabufV1 for Dmabuf {
|
|||||||
async fn get_default_feedback(
|
async fn get_default_feedback(
|
||||||
&self,
|
&self,
|
||||||
client: &mut Client,
|
client: &mut Client,
|
||||||
_sender_id: ObjectId,
|
sender_id: ObjectId,
|
||||||
id: ObjectId,
|
id: ObjectId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if self.version < 3 {
|
||||||
|
client
|
||||||
|
.display()
|
||||||
|
.error(
|
||||||
|
client,
|
||||||
|
sender_id,
|
||||||
|
id,
|
||||||
|
71,
|
||||||
|
"Can't call get_default_feedback on version < 4 of dmabuf".into(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Err(Error::Custom("Protocol error".into()));
|
||||||
|
}
|
||||||
// Create feedback object for default (non-surface-specific) settings
|
// Create feedback object for default (non-surface-specific) settings
|
||||||
let feedback = client.insert(id, DmabufFeedback);
|
let feedback = client.insert(id, DmabufFeedback(client.get::<Dmabuf>(sender_id).unwrap()));
|
||||||
feedback.send_params(client, id).await?;
|
feedback.send_params(client, id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -94,15 +155,13 @@ impl ZwpLinuxDmabufV1 for Dmabuf {
|
|||||||
async fn get_surface_feedback(
|
async fn get_surface_feedback(
|
||||||
&self,
|
&self,
|
||||||
client: &mut Client,
|
client: &mut Client,
|
||||||
_sender_id: ObjectId,
|
sender_id: ObjectId,
|
||||||
id: ObjectId,
|
id: ObjectId,
|
||||||
_surface: ObjectId,
|
_surface: ObjectId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Create feedback object for surface-specific settings
|
// Create feedback object for surface-specific settings
|
||||||
// Note: Surface-specific feedback could be optimized based on the surface's
|
// Note: Surface-specific feedback could be optimized based on the surface's
|
||||||
// requirements, but for now we use the same feedback as default
|
// requirements, but for now we use the same feedback as default
|
||||||
let feedback = client.insert(id, DmabufFeedback);
|
self.get_default_feedback(client, sender_id, id).await
|
||||||
feedback.send_params(client, id).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user