Files
server/src/wayland/dmabuf/mod.rs
Schmarni 0ebfc1153e chore(wayland): update waynest
Signed-off-by: Schmarni <marnistromer@gmail.com>
2025-09-30 22:32:09 +02:00

287 lines
7.3 KiB
Rust

pub mod buffer_backing;
pub mod buffer_params;
pub mod feedback;
use super::vulkano_data::VULKANO_CONTEXT;
use crate::{
core::registry::Registry,
wayland::{Client, WaylandError, WaylandResult},
};
use bevy_dmabuf::{
format_mapping::{drm_fourcc_to_vk_format, vk_format_to_srgb},
wgpu_init::vulkan_to_wgpu,
};
use buffer_params::BufferParams;
use drm_fourcc::DrmFourcc;
use feedback::DmabufFeedback;
use rustc_hash::FxHashSet;
use waynest_server::Client as _;
use std::sync::LazyLock;
use vulkano::format::FormatFeatures;
use waynest::ObjectId;
use waynest_protocols::server::stable::linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1;
pub static DMABUF_FORMATS: LazyLock<Vec<(DrmFourcc, u64)>> = LazyLock::new(|| {
let vk = VULKANO_CONTEXT.wait();
let format_modifier_pairs = ALL_DRM_FOURCCS
.iter()
.copied()
.filter_map(|f| Some((f, drm_fourcc_to_vk_format(f)?)))
.filter(|(_, vk_format)| vulkan_to_wgpu(*vk_format).is_some())
.filter(|(_, vk_format)| vk_format_to_srgb(*vk_format).is_some())
.filter_map(|(f, vk_format)| {
Some((
f,
vk.phys_dev
.format_properties(vk_format.try_into().unwrap())
.ok()?
.drm_format_modifier_properties
.into_iter()
.filter(|v| {
v.drm_format_modifier_tiling_features
.contains(FormatFeatures::SAMPLED_IMAGE)
})
.map(|v| v.drm_format_modifier)
.collect::<Vec<_>>(),
))
})
.flat_map(|(f, mods)| mods.into_iter().map(move |modifier| (f, modifier)))
.collect::<FxHashSet<_>>();
let mut format_modifier_pairs = format_modifier_pairs.into_iter().collect::<Vec<_>>();
format_modifier_pairs.sort_by(|(f1, m1), (f2, m2)| {
// Prioritize LINEAR modifier
let linear1 = *m1 == 0;
let linear2 = *m2 == 0;
linear2
.cmp(&linear1) // true = 1, false = 0
.then_with(|| (*f1 as u32).cmp(&(*f2 as u32))) // Sort by format numerically
.then_with(|| m1.cmp(m2)) // Then by modifier
});
format_modifier_pairs
});
/// Main DMA-BUF interface implementation
///
/// This interface allows clients to create wl_buffers from DMA-BUFs.
/// It handles:
/// - Format/modifier advertisement
/// - Buffer parameter creation
/// - Default/surface-specific feedback
///
/// The implementation ensures:
/// - Coherency for read access in dmabuf data
/// - Proper lifetime management of dmabuf file descriptors
/// - Safe handling of buffer attachments
#[derive(Debug, waynest_server::RequestDispatcher)]
#[waynest(error = crate::wayland::WaylandError, connection = crate::wayland::Client)]
pub struct Dmabuf {
// Track supported formats and modifiers
// formats: Mutex<FxHashSet<DrmFormat>>,
// Track active buffer parameters objects by their ID
active_params: Registry<BufferParams>,
pub(self) version: u32,
pub(self) formats: Vec<(DrmFourcc, u64)>,
}
impl Dmabuf {
/// Create a new DMA-BUF interface instance
pub async fn new(client: &mut Client, id: ObjectId, version: u32) -> WaylandResult<Self> {
let dmabuf = Self {
active_params: Registry::new(),
version,
formats: DMABUF_FORMATS.clone(),
};
if version < 3 {
for (format, _) in &dmabuf.formats {
dmabuf.format(client, id, *format as u32).await?;
}
}
// `modifier` is deprecated in version 4
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
pub(crate) fn remove_params(&self, params_id: ObjectId) {
self.active_params.retain(|params| params.id != params_id);
}
}
impl ZwpLinuxDmabufV1 for Dmabuf {
type Connection = crate::wayland::Client;
async fn destroy(
&self,
_client: &mut Self::Connection,
sender_id: ObjectId,
) -> WaylandResult<()> {
self.remove_params(sender_id);
Ok(())
}
async fn create_params(
&self,
client: &mut Self::Connection,
_sender_id: ObjectId,
params_id: ObjectId,
) -> WaylandResult<()> {
// Create new buffer parameters object
let params = client.insert(params_id, BufferParams::new(params_id))?;
self.active_params.add_raw(&params);
Ok(())
}
async fn get_default_feedback(
&self,
client: &mut Self::Connection,
sender_id: ObjectId,
id: ObjectId,
) -> WaylandResult<()> {
if self.version < 3 {
return Err(WaylandError::Fatal {
object_id: id,
code: 71,
message: "Can't call get_default_feedback on version < 4 of dmabuf",
});
}
// Create feedback object for default (non-surface-specific) settings
let feedback = client.insert(id, DmabufFeedback(client.get::<Dmabuf>(sender_id).unwrap()))?;
feedback.send_params(client, id).await?;
Ok(())
}
async fn get_surface_feedback(
&self,
client: &mut Self::Connection,
sender_id: ObjectId,
id: ObjectId,
_surface: ObjectId,
) -> WaylandResult<()> {
// Create feedback object for surface-specific settings
// Note: Surface-specific feedback could be optimized based on the surface's
// requirements, but for now we use the same feedback as default
self.get_default_feedback(client, sender_id, id).await
}
}
pub const ALL_DRM_FOURCCS: [DrmFourcc; 105] = [
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::Bgr233,
DrmFourcc::Bgr565,
DrmFourcc::Bgr565_a8,
DrmFourcc::Bgr888,
DrmFourcc::Bgr888_a8,
DrmFourcc::Bgra1010102,
DrmFourcc::Bgra4444,
DrmFourcc::Bgra5551,
DrmFourcc::Bgra8888,
DrmFourcc::Bgrx1010102,
DrmFourcc::Bgrx4444,
DrmFourcc::Bgrx5551,
DrmFourcc::Bgrx8888,
DrmFourcc::Bgrx8888_a8,
DrmFourcc::Big_endian,
DrmFourcc::C8,
DrmFourcc::Gr1616,
DrmFourcc::Gr88,
DrmFourcc::Nv12,
DrmFourcc::Nv15,
DrmFourcc::Nv16,
DrmFourcc::Nv21,
DrmFourcc::Nv24,
DrmFourcc::Nv42,
DrmFourcc::Nv61,
DrmFourcc::P010,
DrmFourcc::P012,
DrmFourcc::P016,
DrmFourcc::P210,
DrmFourcc::Q401,
DrmFourcc::Q410,
DrmFourcc::R16,
DrmFourcc::R8,
DrmFourcc::Rg1616,
DrmFourcc::Rg88,
DrmFourcc::Rgb332,
DrmFourcc::Rgb565,
DrmFourcc::Rgb565_a8,
DrmFourcc::Rgb888,
DrmFourcc::Rgb888_a8,
DrmFourcc::Rgba1010102,
DrmFourcc::Rgba4444,
DrmFourcc::Rgba5551,
DrmFourcc::Rgba8888,
DrmFourcc::Rgbx1010102,
DrmFourcc::Rgbx4444,
DrmFourcc::Rgbx5551,
DrmFourcc::Rgbx8888,
DrmFourcc::Rgbx8888_a8,
DrmFourcc::Uyvy,
DrmFourcc::Vuy101010,
DrmFourcc::Vuy888,
DrmFourcc::Vyuy,
DrmFourcc::X0l0,
DrmFourcc::X0l2,
DrmFourcc::Xbgr1555,
DrmFourcc::Xbgr16161616f,
DrmFourcc::Xbgr2101010,
DrmFourcc::Xbgr4444,
DrmFourcc::Xbgr8888,
DrmFourcc::Xbgr8888_a8,
DrmFourcc::Xrgb1555,
DrmFourcc::Xrgb16161616f,
DrmFourcc::Xrgb2101010,
DrmFourcc::Xrgb4444,
DrmFourcc::Xrgb8888,
DrmFourcc::Xrgb8888_a8,
DrmFourcc::Xvyu12_16161616,
DrmFourcc::Xvyu16161616,
DrmFourcc::Xvyu2101010,
DrmFourcc::Xyuv8888,
DrmFourcc::Y0l0,
DrmFourcc::Y0l2,
DrmFourcc::Y210,
DrmFourcc::Y212,
DrmFourcc::Y216,
DrmFourcc::Y410,
DrmFourcc::Y412,
DrmFourcc::Y416,
DrmFourcc::Yuv410,
DrmFourcc::Yuv411,
DrmFourcc::Yuv420,
DrmFourcc::Yuv420_10bit,
DrmFourcc::Yuv420_8bit,
DrmFourcc::Yuv422,
DrmFourcc::Yuv444,
DrmFourcc::Yuyv,
DrmFourcc::Yvu410,
DrmFourcc::Yvu411,
DrmFourcc::Yvu420,
DrmFourcc::Yvu422,
DrmFourcc::Yvu444,
DrmFourcc::Yvyu,
];