diff --git a/src/clientmem.rs b/src/clientmem.rs index 69f9c530..c01b26f2 100644 --- a/src/clientmem.rs +++ b/src/clientmem.rs @@ -54,8 +54,9 @@ impl ClientMem { read_only: bool, client: Option<&Client>, cpu: Option<&Rc>, + is_udmabuf: bool, ) -> Result { - Self::new2(fd, len, read_only, client, cpu, c::MAP_SHARED) + Self::new2(fd, len, read_only, client, cpu, c::MAP_SHARED, is_udmabuf) } pub fn new_private( @@ -65,7 +66,7 @@ impl ClientMem { client: Option<&Client>, cpu: Option<&Rc>, ) -> Result { - Self::new2(fd, len, read_only, client, cpu, c::MAP_PRIVATE) + Self::new2(fd, len, read_only, client, cpu, c::MAP_PRIVATE, false) } fn new2( @@ -75,10 +76,12 @@ impl ClientMem { client: Option<&Client>, cpu: Option<&Rc>, flags: c::c_int, + is_udmabuf: bool, ) -> Result { - let mut sigbus_impossible = false; + let mut sigbus_impossible = is_udmabuf; let mut real_size = None; - if let Ok(seals) = uapi::fcntl_get_seals(fd.raw()) + if !sigbus_impossible + && let Ok(seals) = uapi::fcntl_get_seals(fd.raw()) && seals & c::F_SEAL_SHRINK != 0 && let Ok(stat) = uapi::fstat(fd.raw()) { diff --git a/src/format.rs b/src/format.rs index b4f7c3dc..cd8d1f2b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -20,7 +20,6 @@ use { #[derive(Copy, Clone, Debug)] pub struct FormatShmInfo { - pub bpp: u32, pub gl_format: GLint, pub gl_internal_format: GLenum, pub gl_type: GLint, @@ -38,6 +37,7 @@ pub struct Format { pub opaque: Option<&'static Format>, pub shm_info: Option, pub config: ConfigFormat, + pub bpp: u32, } const fn default(config: ConfigFormat) -> Format { @@ -52,6 +52,7 @@ const fn default(config: ConfigFormat) -> Format { opaque: None, shm_info: None, config, + bpp: 4, } } @@ -159,12 +160,12 @@ pub fn map_wayland_format_id(id: u32) -> u32 { pub static ARGB8888: &Format = &Format { name: "argb8888", shm_info: Some(FormatShmInfo { - bpp: 4, gl_format: GL_BGRA_EXT, gl_internal_format: GL_RGBA8, gl_type: GL_UNSIGNED_BYTE, }), vk_format: vk::Format::B8G8R8A8_UNORM, + bpp: 4, drm: ARGB8888_DRM, wl_id: Some(ARGB8888_ID), external_only_guess: false, @@ -177,12 +178,12 @@ pub static ARGB8888: &Format = &Format { pub static XRGB8888: &Format = &Format { name: "xrgb8888", shm_info: Some(FormatShmInfo { - bpp: 4, gl_format: GL_BGRA_EXT, gl_internal_format: GL_RGBA8, gl_type: GL_UNSIGNED_BYTE, }), vk_format: vk::Format::B8G8R8A8_UNORM, + bpp: 4, drm: XRGB8888_DRM, wl_id: Some(XRGB8888_ID), external_only_guess: false, @@ -195,12 +196,12 @@ pub static XRGB8888: &Format = &Format { static ABGR8888: &Format = &Format { name: "abgr8888", shm_info: Some(FormatShmInfo { - bpp: 4, gl_format: GL_RGBA, gl_internal_format: GL_RGBA8, gl_type: GL_UNSIGNED_BYTE, }), vk_format: vk::Format::R8G8B8A8_UNORM, + bpp: 4, drm: fourcc_code('A', 'B', '2', '4'), wl_id: None, external_only_guess: false, @@ -213,12 +214,12 @@ static ABGR8888: &Format = &Format { static XBGR8888: &Format = &Format { name: "xbgr8888", shm_info: Some(FormatShmInfo { - bpp: 4, gl_format: GL_RGBA, gl_internal_format: GL_RGBA8, gl_type: GL_UNSIGNED_BYTE, }), vk_format: vk::Format::R8G8B8A8_UNORM, + bpp: 4, drm: fourcc_code('X', 'B', '2', '4'), wl_id: None, external_only_guess: false, @@ -231,6 +232,7 @@ static XBGR8888: &Format = &Format { static R8: &Format = &Format { name: "r8", vk_format: vk::Format::R8_UNORM, + bpp: 1, drm: fourcc_code('R', '8', ' ', ' '), pipewire: SPA_VIDEO_FORMAT_GRAY8, ..default(ConfigFormat::R8) @@ -239,6 +241,7 @@ static R8: &Format = &Format { static GR88: &Format = &Format { name: "gr88", vk_format: vk::Format::R8G8_UNORM, + bpp: 2, drm: fourcc_code('G', 'R', '8', '8'), ..default(ConfigFormat::GR88) }; @@ -246,6 +249,7 @@ static GR88: &Format = &Format { static RGB888: &Format = &Format { name: "rgb888", vk_format: vk::Format::B8G8R8_UNORM, + bpp: 3, drm: fourcc_code('R', 'G', '2', '4'), pipewire: SPA_VIDEO_FORMAT_BGR, ..default(ConfigFormat::RGB888) @@ -254,6 +258,7 @@ static RGB888: &Format = &Format { static BGR888: &Format = &Format { name: "bgr888", vk_format: vk::Format::R8G8B8_UNORM, + bpp: 3, drm: fourcc_code('B', 'G', '2', '4'), pipewire: SPA_VIDEO_FORMAT_RGB, ..default(ConfigFormat::BGR888) @@ -262,6 +267,7 @@ static BGR888: &Format = &Format { static RGBA4444: &Format = &Format { name: "rgba4444", vk_format: vk::Format::R4G4B4A4_UNORM_PACK16, + bpp: 2, drm: fourcc_code('R', 'A', '1', '2'), has_alpha: true, opaque: Some(RGBX4444), @@ -271,6 +277,7 @@ static RGBA4444: &Format = &Format { static RGBX4444: &Format = &Format { name: "rgbx4444", vk_format: vk::Format::R4G4B4A4_UNORM_PACK16, + bpp: 2, drm: fourcc_code('R', 'X', '1', '2'), ..default(ConfigFormat::RGBX4444) }; @@ -278,6 +285,7 @@ static RGBX4444: &Format = &Format { static BGRA4444: &Format = &Format { name: "bgra4444", vk_format: vk::Format::B4G4R4A4_UNORM_PACK16, + bpp: 2, drm: fourcc_code('B', 'A', '1', '2'), has_alpha: true, opaque: Some(BGRX4444), @@ -287,6 +295,7 @@ static BGRA4444: &Format = &Format { static BGRX4444: &Format = &Format { name: "bgrx4444", vk_format: vk::Format::B4G4R4A4_UNORM_PACK16, + bpp: 2, drm: fourcc_code('B', 'X', '1', '2'), ..default(ConfigFormat::BGRX4444) }; @@ -294,6 +303,7 @@ static BGRX4444: &Format = &Format { static RGB565: &Format = &Format { name: "rgb565", vk_format: vk::Format::R5G6B5_UNORM_PACK16, + bpp: 2, drm: fourcc_code('R', 'G', '1', '6'), pipewire: SPA_VIDEO_FORMAT_BGR16, ..default(ConfigFormat::RGB565) @@ -302,6 +312,7 @@ static RGB565: &Format = &Format { static BGR565: &Format = &Format { name: "bgr565", vk_format: vk::Format::B5G6R5_UNORM_PACK16, + bpp: 2, drm: fourcc_code('B', 'G', '1', '6'), pipewire: SPA_VIDEO_FORMAT_RGB16, ..default(ConfigFormat::BGR565) @@ -310,6 +321,7 @@ static BGR565: &Format = &Format { static RGBA5551: &Format = &Format { name: "rgba5551", vk_format: vk::Format::R5G5B5A1_UNORM_PACK16, + bpp: 2, drm: fourcc_code('R', 'A', '1', '5'), has_alpha: true, opaque: Some(RGBX5551), @@ -319,6 +331,7 @@ static RGBA5551: &Format = &Format { static RGBX5551: &Format = &Format { name: "rgbx5551", vk_format: vk::Format::R5G5B5A1_UNORM_PACK16, + bpp: 2, drm: fourcc_code('R', 'X', '1', '5'), ..default(ConfigFormat::RGBX5551) }; @@ -326,6 +339,7 @@ static RGBX5551: &Format = &Format { static BGRA5551: &Format = &Format { name: "bgra5551", vk_format: vk::Format::B5G5R5A1_UNORM_PACK16, + bpp: 2, drm: fourcc_code('B', 'A', '1', '5'), has_alpha: true, opaque: Some(BGRX5551), @@ -335,6 +349,7 @@ static BGRA5551: &Format = &Format { static BGRX5551: &Format = &Format { name: "bgrx5551", vk_format: vk::Format::B5G5R5A1_UNORM_PACK16, + bpp: 2, drm: fourcc_code('B', 'X', '1', '5'), ..default(ConfigFormat::BGRX5551) }; @@ -342,6 +357,7 @@ static BGRX5551: &Format = &Format { static ARGB1555: &Format = &Format { name: "argb1555", vk_format: vk::Format::A1R5G5B5_UNORM_PACK16, + bpp: 2, drm: fourcc_code('A', 'R', '1', '5'), has_alpha: true, opaque: Some(XRGB1555), @@ -351,6 +367,7 @@ static ARGB1555: &Format = &Format { static XRGB1555: &Format = &Format { name: "xrgb1555", vk_format: vk::Format::A1R5G5B5_UNORM_PACK16, + bpp: 2, drm: fourcc_code('X', 'R', '1', '5'), pipewire: SPA_VIDEO_FORMAT_BGR15, ..default(ConfigFormat::XRGB1555) @@ -359,6 +376,7 @@ static XRGB1555: &Format = &Format { static ARGB2101010: &Format = &Format { name: "argb2101010", vk_format: vk::Format::A2R10G10B10_UNORM_PACK32, + bpp: 4, drm: fourcc_code('A', 'R', '3', '0'), has_alpha: true, opaque: Some(XRGB2101010), @@ -369,6 +387,7 @@ static ARGB2101010: &Format = &Format { static XRGB2101010: &Format = &Format { name: "xrgb2101010", vk_format: vk::Format::A2R10G10B10_UNORM_PACK32, + bpp: 4, drm: fourcc_code('X', 'R', '3', '0'), pipewire: SPA_VIDEO_FORMAT_xRGB_210LE, ..default(ConfigFormat::XRGB2101010) @@ -377,6 +396,7 @@ static XRGB2101010: &Format = &Format { static ABGR2101010: &Format = &Format { name: "abgr2101010", vk_format: vk::Format::A2B10G10R10_UNORM_PACK32, + bpp: 4, drm: fourcc_code('A', 'B', '3', '0'), has_alpha: true, opaque: Some(XBGR2101010), @@ -387,6 +407,7 @@ static ABGR2101010: &Format = &Format { static XBGR2101010: &Format = &Format { name: "xbgr2101010", vk_format: vk::Format::A2B10G10R10_UNORM_PACK32, + bpp: 4, drm: fourcc_code('X', 'B', '3', '0'), pipewire: SPA_VIDEO_FORMAT_xBGR_210LE, ..default(ConfigFormat::XBGR2101010) @@ -395,6 +416,7 @@ static XBGR2101010: &Format = &Format { static ABGR16161616: &Format = &Format { name: "abgr16161616", vk_format: vk::Format::R16G16B16A16_UNORM, + bpp: 8, drm: fourcc_code('A', 'B', '4', '8'), has_alpha: true, opaque: Some(XBGR16161616), @@ -404,6 +426,7 @@ static ABGR16161616: &Format = &Format { static XBGR16161616: &Format = &Format { name: "xbgr16161616", vk_format: vk::Format::R16G16B16A16_UNORM, + bpp: 8, drm: fourcc_code('X', 'B', '4', '8'), ..default(ConfigFormat::XBGR16161616) }; @@ -411,6 +434,7 @@ static XBGR16161616: &Format = &Format { pub static ABGR16161616F: &Format = &Format { name: "abgr16161616f", vk_format: vk::Format::R16G16B16A16_SFLOAT, + bpp: 8, drm: fourcc_code('A', 'B', '4', 'H'), has_alpha: true, opaque: Some(XBGR16161616F), @@ -420,6 +444,7 @@ pub static ABGR16161616F: &Format = &Format { static XBGR16161616F: &Format = &Format { name: "xbgr16161616f", vk_format: vk::Format::R16G16B16A16_SFLOAT, + bpp: 8, drm: fourcc_code('X', 'B', '4', 'H'), ..default(ConfigFormat::XBGR16161616F) }; diff --git a/src/gfx_api.rs b/src/gfx_api.rs index 1b0fa1f7..86801b11 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -824,10 +824,12 @@ pub trait GfxContext: Debug { dmabuf: &OwnedFd, offset: usize, size: usize, + format: &'static Format, ) -> Result, GfxError> { let _ = dmabuf; let _ = offset; let _ = size; + let _ = format; #[derive(Debug, Error)] #[error("Host buffers are not supported")] @@ -850,6 +852,7 @@ pub struct GfxFormat { pub format: &'static Format, pub read_modifiers: IndexSet, pub write_modifiers: IndexMap, + pub supports_shm: bool, } #[derive(Error)] @@ -879,6 +882,7 @@ impl GfxFormat { .map(|(m, v)| (*m, v.clone())) .filter(|(m, _)| other.read_modifiers.contains(m)) .collect(), + supports_shm: self.supports_shm && other.supports_shm, } } } diff --git a/src/gfx_apis/gl/egl/display.rs b/src/gfx_apis/gl/egl/display.rs index c62ad4c9..a5bff244 100644 --- a/src/gfx_apis/gl/egl/display.rs +++ b/src/gfx_apis/gl/egl/display.rs @@ -201,13 +201,17 @@ impl EglDisplay { } read_modifiers.insert(modifier.modifier); } - if !read_modifiers.is_empty() || !write_modifiers.is_empty() { + if !read_modifiers.is_empty() + || !write_modifiers.is_empty() + || format.format.shm_info.is_some() + { formats.insert( drm, GfxFormat { format: format.format, read_modifiers, write_modifiers, + supports_shm: format.format.shm_info.is_some(), }, ); } diff --git a/src/gfx_apis/gl/gl/texture.rs b/src/gfx_apis/gl/gl/texture.rs index f1491bd9..81a6f970 100644 --- a/src/gfx_apis/gl/gl/texture.rs +++ b/src/gfx_apis/gl/gl/texture.rs @@ -90,7 +90,7 @@ impl GlTexture { (gles.glBindTexture)(GL_TEXTURE_2D, tex); (gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); (gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - (gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / shm_info.bpp as GLint); + (gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint); (gles.glTexImage2D)( GL_TEXTURE_2D, 0, diff --git a/src/gfx_apis/gl/renderer/texture.rs b/src/gfx_apis/gl/renderer/texture.rs index e6b1d7da..b1170329 100644 --- a/src/gfx_apis/gl/renderer/texture.rs +++ b/src/gfx_apis/gl/renderer/texture.rs @@ -90,7 +90,7 @@ impl AsyncShmGfxTexture for Texture { (gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); (gles.glPixelStorei)( GL_UNPACK_ROW_LENGTH_EXT, - self.gl.stride / shm_info.bpp as GLint, + self.gl.stride / self.format.bpp as GLint, ); (gles.glTexImage2D)( GL_TEXTURE_2D, diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index 1c512929..31844fb4 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -179,8 +179,6 @@ pub enum VulkanError { InvalidStride, #[error("Shm stride and height do not match buffer size")] InvalidBufferSize, - #[error("Buffer format {0} is not supported for shm buffers in Vulkan context")] - UnsupportedShmFormat(&'static str), #[error("Only BO_USE_RENDERING and BO_USE_WRITE are supported")] UnsupportedBufferUsage, #[error("None of the supplied modifiers are supported")] @@ -223,6 +221,8 @@ pub enum VulkanError { GetFl(#[source] OsError), #[error("GBM implementation cannot be used with software renderer")] SoftwareRendererNotUsable, + #[error("DMABUF buffer offsets must be aligned to 4 bytes and the pixel size")] + DmaBufBufferOffsetAlignment, } impl From for GfxError { @@ -401,12 +401,13 @@ impl GfxContext for Context { dmabuf: &OwnedFd, offset: usize, size: usize, + format: &'static Format, ) -> Result, GfxError> { self.0.check_defunct()?; - let buffer = self - .0 - .device - .create_dmabuf_buffer(dmabuf, offset as u64, size as u64)?; + let buffer = + self.0 + .device + .create_dmabuf_buffer(dmabuf, offset as u64, size as u64, format)?; Ok(buffer) } } diff --git a/src/gfx_apis/vulkan/bo_allocator.rs b/src/gfx_apis/vulkan/bo_allocator.rs index 6a6946f8..8e8d2200 100644 --- a/src/gfx_apis/vulkan/bo_allocator.rs +++ b/src/gfx_apis/vulkan/bo_allocator.rs @@ -457,10 +457,7 @@ impl Allocator for VulkanBoAllocator { impl VulkanBo { fn map(self: &Rc, write: bool) -> Result { let format = self.buf.format; - let Some(shm_info) = &format.shm_info else { - return Err(VulkanError::ShmNotSupported); - }; - let stride = self.buf.width as u32 * shm_info.bpp; + let stride = self.buf.width as u32 * format.bpp; let size = self.buf.height as u32 * stride; let data = &self.allocator; let staging = diff --git a/src/gfx_apis/vulkan/dmabuf_buffer.rs b/src/gfx_apis/vulkan/dmabuf_buffer.rs index fa13aaaf..91f8aaae 100644 --- a/src/gfx_apis/vulkan/dmabuf_buffer.rs +++ b/src/gfx_apis/vulkan/dmabuf_buffer.rs @@ -1,5 +1,6 @@ use { crate::{ + format::Format, gfx_api::GfxBuffer, gfx_apis::vulkan::{VulkanError, device::VulkanDevice}, utils::on_drop::OnDrop, @@ -9,13 +10,15 @@ use { vk::{ self, BufferCreateInfo, BufferUsageFlags, ExternalMemoryBufferCreateInfo, ExternalMemoryHandleTypeFlags, ImportMemoryFdInfoKHR, MemoryAllocateInfo, - MemoryFdPropertiesKHR, MemoryPropertyFlags, + MemoryDedicatedAllocateInfo, MemoryFdPropertiesKHR, MemoryPropertyFlags, }, }, std::{any::Any, rc::Rc}, uapi::OwnedFd, }; +pub(super) const TRANSFER_QUEUE_BUFFER_ALIGNMENT: u64 = 4; + pub struct VulkanDmabufBuffer { pub(super) device: Rc, pub(super) size: u64, @@ -30,7 +33,11 @@ impl VulkanDevice { dmabuf: &OwnedFd, offset: u64, size: u64, + format: &'static Format, ) -> Result, VulkanError> { + if offset % TRANSFER_QUEUE_BUFFER_ALIGNMENT != 0 || offset % format.bpp as u64 != 0 { + return Err(VulkanError::DmaBufBufferOffsetAlignment); + } let mut memory_fd_properties = MemoryFdPropertiesKHR::default(); unsafe { self.external_memory_fd @@ -66,13 +73,15 @@ impl VulkanDevice { let fd = uapi::fcntl_dupfd_cloexec(dmabuf.raw(), 0).map_err(|e| VulkanError::Dupfd(e.into()))?; let memory = { + let mut dedicated = MemoryDedicatedAllocateInfo::default().buffer(buffer); let mut import_info = ImportMemoryFdInfoKHR::default() .fd(fd.raw()) .handle_type(ExternalMemoryHandleTypeFlags::DMA_BUF_EXT); let allocate_info = MemoryAllocateInfo::default() .allocation_size(requirements.size) .memory_type_index(memory_type) - .push_next(&mut import_info); + .push_next(&mut import_info) + .push_next(&mut dedicated); unsafe { self.device .allocate_memory(&allocate_info, None) diff --git a/src/gfx_apis/vulkan/format.rs b/src/gfx_apis/vulkan/format.rs index d8395254..71386749 100644 --- a/src/gfx_apis/vulkan/format.rs +++ b/src/gfx_apis/vulkan/format.rs @@ -171,9 +171,6 @@ impl VulkanInstance { format: &Format, props: &FormatProperties, ) -> Result, VulkanError> { - if format.shm_info.is_none() { - return Ok(None); - } self.load_internal_format(phy_dev, format, props, SHM_FEATURES, SHM_USAGE) } diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 6aae40b4..ea3bfdd9 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -345,6 +345,7 @@ impl VulkanDevice { ) }) .collect(), + supports_shm: vk.shm.is_some(), }, ) }) diff --git a/src/gfx_apis/vulkan/shm_image.rs b/src/gfx_apis/vulkan/shm_image.rs index 567d33f8..2f50a721 100644 --- a/src/gfx_apis/vulkan/shm_image.rs +++ b/src/gfx_apis/vulkan/shm_image.rs @@ -1,7 +1,7 @@ use { crate::{ cpu_worker::CpuWorker, - format::{Format, FormatShmInfo}, + format::Format, gfx_api::SyncFile, gfx_apis::vulkan::{ VulkanError, @@ -22,18 +22,17 @@ use { CopyImageToBufferInfo2, DependencyInfoKHR, DeviceSize, Extent3D, ImageAspectFlags, ImageCreateInfo, ImageLayout, ImageSubresourceLayers, ImageSubresourceRange, ImageTiling, ImageType, ImageUsageFlags, ImageViewCreateInfo, ImageViewType, Offset3D, - PipelineStageFlags2, SampleCountFlags, SharingMode, SubmitInfo2, + PipelineStageFlags2, QUEUE_FAMILY_FOREIGN_EXT, SampleCountFlags, SharingMode, SubmitInfo2, }, gpu_alloc::UsageFlags, isnt::std_1::primitive::IsntSliceExt, - std::{cell::Cell, ptr, rc::Rc, slice}, + std::{cell::Cell, mem, ptr, rc::Rc, slice}, }; pub struct VulkanShmImage { pub(super) size: DeviceSize, pub(super) stride: u32, pub(super) _allocation: VulkanAllocation, - pub(super) shm_info: &'static FormatShmInfo, pub(super) async_data: Option, } @@ -68,7 +67,7 @@ impl VulkanShmImage { if full { builder = builder .buffer_image_height(img.height) - .buffer_row_length(img.stride / self.shm_info.bpp); + .buffer_row_length(img.stride / img.format.bpp); } builder }; @@ -99,7 +98,7 @@ impl VulkanShmImage { damage.width() as u32, damage.height() as u32, )); - total_size += damage.width() as u32 * damage.height() as u32 * self.shm_info.bpp; + total_size += damage.width() as u32 * damage.height() as u32 * img.format.bpp; } cpy = &cpy_many[..]; } else { @@ -124,7 +123,7 @@ impl VulkanShmImage { let width = cpy.image_extent.width as usize; let height = cpy.image_extent.height as usize; let stride = self.stride as usize; - let bpp = self.shm_info.bpp as usize; + let bpp = img.format.bpp as usize; for dy in 0..height { let lo = (y + dy) * stride + x * bpp; let len = width * bpp; @@ -143,6 +142,7 @@ impl VulkanShmImage { cpy, false, TransferType::Upload, + false, )?; let future = img.renderer.eng.spawn( "await upload", @@ -160,6 +160,7 @@ impl VulkanShmImage { regions: &[BufferImageCopy2], use_transfer_queue: bool, tt: TransferType, + foreign_buffer: bool, ) -> Result< ( Rc, @@ -169,22 +170,50 @@ impl VulkanShmImage { ), VulkanError, > { - let memory_barrier = |sam, ssm, dam, dsm| { - BufferMemoryBarrier2::default() - .buffer(buffer) - .offset(0) - .size(size) - .src_access_mask(sam) - .src_stage_mask(ssm) - .dst_access_mask(dam) - .dst_stage_mask(dsm) - }; let mut transfer_queue_family_idx = img.renderer.device.graphics_queue_idx; if use_transfer_queue && let Some(idx) = img.renderer.device.distinct_transfer_queue_family_idx { transfer_queue_family_idx = idx; } + let memory_barrier = |release| { + let mut sq; + let mut sam; + let mut ssm; + if foreign_buffer { + sq = QUEUE_FAMILY_FOREIGN_EXT; + sam = AccessFlags2::NONE; + ssm = PipelineStageFlags2::NONE; + } else { + sq = transfer_queue_family_idx; + sam = match tt { + TransferType::Upload => AccessFlags2::HOST_WRITE, + TransferType::Download => AccessFlags2::HOST_READ, + }; + ssm = PipelineStageFlags2::HOST; + } + let mut dq = transfer_queue_family_idx; + let mut dam = match tt { + TransferType::Upload => AccessFlags2::TRANSFER_READ, + TransferType::Download => AccessFlags2::TRANSFER_WRITE, + }; + let mut dsm = PipelineStageFlags2::TRANSFER; + if release { + mem::swap(&mut sq, &mut dq); + mem::swap(&mut sam, &mut dam); + mem::swap(&mut ssm, &mut dsm); + } + BufferMemoryBarrier2::default() + .buffer(buffer) + .offset(0) + .size(size) + .src_queue_family_index(sq) + .src_access_mask(sam) + .src_stage_mask(ssm) + .dst_queue_family_index(dq) + .dst_access_mask(dam) + .dst_stage_mask(dsm) + }; let mut initial_image_barrier = image_barrier() .image(img.image) .src_queue_family_index(img.renderer.device.graphics_queue_idx) @@ -208,18 +237,7 @@ impl VulkanShmImage { .src_access_mask(AccessFlags2::SHADER_SAMPLED_READ) .src_stage_mask(PipelineStageFlags2::FRAGMENT_SHADER) } - let initial_buffer_barrier = memory_barrier( - match tt { - TransferType::Upload => AccessFlags2::HOST_WRITE, - TransferType::Download => AccessFlags2::HOST_READ, - }, - PipelineStageFlags2::HOST, - match tt { - TransferType::Upload => AccessFlags2::TRANSFER_READ, - TransferType::Download => AccessFlags2::TRANSFER_WRITE, - }, - PipelineStageFlags2::TRANSFER, - ); + let initial_buffer_barrier = memory_barrier(false); let initial_dep_info = DependencyInfoKHR::default() .buffer_memory_barriers(slice::from_ref(&initial_buffer_barrier)) .image_memory_barriers(slice::from_ref(&initial_image_barrier)); @@ -248,18 +266,7 @@ impl VulkanShmImage { }) .dst_stage_mask(PipelineStageFlags2::FRAGMENT_SHADER); } - let final_buffer_barrier = memory_barrier( - match tt { - TransferType::Upload => AccessFlags2::TRANSFER_READ, - TransferType::Download => AccessFlags2::TRANSFER_WRITE, - }, - PipelineStageFlags2::TRANSFER, - match tt { - TransferType::Upload => AccessFlags2::HOST_WRITE, - TransferType::Download => AccessFlags2::HOST_READ, - }, - PipelineStageFlags2::HOST, - ); + let final_buffer_barrier = memory_barrier(true); let final_dep_info = DependencyInfoKHR::default() .buffer_memory_barriers(slice::from_ref(&final_buffer_barrier)) .image_memory_barriers(slice::from_ref(&final_image_barrier)); @@ -359,16 +366,13 @@ impl VulkanRenderer { for_download: bool, cpu_worker: Option<&Rc>, ) -> Result, VulkanError> { - let Some(shm_info) = &format.shm_info else { - return Err(VulkanError::UnsupportedShmFormat(format.name)); - }; if width <= 0 || height <= 0 || stride <= 0 { return Err(VulkanError::NonPositiveImageSize); } let width = width as u32; let height = height as u32; let stride = stride as u32; - if stride % shm_info.bpp != 0 || stride / shm_info.bpp < width { + if stride % format.bpp != 0 || stride / format.bpp < width { return Err(VulkanError::InvalidStride); } let vk_format = self @@ -453,7 +457,6 @@ impl VulkanRenderer { size, stride, _allocation: allocation, - shm_info, async_data, }; destroy_image.forget(); diff --git a/src/gfx_apis/vulkan/transfer.rs b/src/gfx_apis/vulkan/transfer.rs index ce358905..e7378c07 100644 --- a/src/gfx_apis/vulkan/transfer.rs +++ b/src/gfx_apis/vulkan/transfer.rs @@ -13,7 +13,7 @@ use { gfx_apis::vulkan::{ VulkanError, command::VulkanCommandBuffer, - dmabuf_buffer::VulkanDmabufBuffer, + dmabuf_buffer::{TRANSFER_QUEUE_BUFFER_ALIGNMENT, VulkanDmabufBuffer}, fence::VulkanFence, image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory}, renderer::image_barrier, @@ -227,8 +227,25 @@ impl VulkanShmImage { let mut copies_ref = data.regions.borrow_mut(); let copies = &mut *copies_ref; copies.clear(); - let mut copy = |x, y, width, height| { - let buffer_offset = (y as u32 * img.stride + x as u32 * self.shm_info.bpp) as u64; + let mut copy = |mut x, mut y, mut width, mut height| { + let x_orig = x; + let width_orig = width; + let mut buffer_offset; + loop { + buffer_offset = (y as u32 * img.stride + x as u32 * img.format.bpp) as u64; + if buffer_offset.is_multiple_of(TRANSFER_QUEUE_BUFFER_ALIGNMENT) { + break; + } + if x > 0 { + x -= 1; + width += 1; + } else { + y -= 1; + height += 1; + x = x_orig; + width = width_orig; + } + } let copy = BufferImageCopy2::default() .buffer_offset(buffer_offset + extra_offset) .image_offset(Offset3D { x, y, z: 0 }) @@ -244,7 +261,7 @@ impl VulkanShmImage { layer_count: 1, }) .buffer_image_height(img.height) - .buffer_row_length(img.stride / self.shm_info.bpp); + .buffer_row_length(img.stride / img.format.bpp); copies.push(copy); }; let (width_mask, height_mask) = img.renderer.device.transfer_granularity_mask; @@ -451,7 +468,7 @@ impl VulkanShmImage { } job.work.width = img.width as _; job.work.stride = img.stride as _; - job.work.bpp = self.shm_info.bpp as _; + job.work.bpp = img.format.bpp as _; job.work.rects.clear(); for copy in copies { job.work.rects.push( @@ -472,7 +489,7 @@ impl VulkanShmImage { for copy in copies { min_offset = min_offset.min(copy.buffer_offset); let len = img.stride * (copy.image_extent.height - 1) - + copy.image_extent.width * self.shm_info.bpp; + + copy.image_extent.width * img.format.bpp; max_offset = max_offset.max(copy.buffer_offset + len as u64); } let mut job = data.io_job.take().unwrap_or_else(|| { @@ -520,19 +537,26 @@ impl VulkanShmImage { } img.renderer.check_defunct()?; let regions = &*data.regions.borrow(); - let (buffer, size) = match data.staging.get() { + let (buffer, size, foreign_buffer) = match data.staging.get() { Some(s) => { let staging = s.staging.get().unwrap(); staging.upload(|_, _| ())?; - (staging.buffer, staging.size) + (staging.buffer, staging.size, false) } _ => { let host_buffer = data.buffer.get().unwrap(); - (host_buffer.buffer, host_buffer.size) + (host_buffer.buffer, host_buffer.size, true) } }; - let (cmd, fence, sync_file, point) = - self.submit_buffer_image_copy(img, buffer, size, regions, true, TransferType::Upload)?; + let (cmd, fence, sync_file, point) = self.submit_buffer_image_copy( + img, + buffer, + size, + regions, + true, + TransferType::Upload, + foreign_buffer, + )?; img.queue_state.set(QueueState::Releasing); let future = img.renderer.eng.spawn( "await async upload", @@ -566,6 +590,7 @@ impl VulkanShmImage { copies, true, TransferType::Download, + false, )?; img.queue_state.set(QueueState::Releasing); let future = img.renderer.eng.spawn( diff --git a/src/ifs/wl_buffer.rs b/src/ifs/wl_buffer.rs index 39b590c1..cbb0a2cc 100644 --- a/src/ifs/wl_buffer.rs +++ b/src/ifs/wl_buffer.rs @@ -108,20 +108,38 @@ impl WlBuffer { stride: i32, format: &'static Format, mem: &Rc, + udmabuf: Option<(&Rc, usize)>, ) -> Result { - let Some(shm_info) = &format.shm_info else { - return Err(WlBufferError::UnsupportedShmFormat(format.name)); - }; let bytes = stride as u64 * height as u64; let required = bytes + offset as u64; if required > mem.len() as u64 { return Err(WlBufferError::OutOfBounds); } let mem = Rc::new(mem.offset(offset)); - let min_row_size = width as u64 * shm_info.bpp as u64; + let min_row_size = width as u64 * format.bpp as u64; if (stride as u64) < min_row_size { return Err(WlBufferError::StrideTooSmall); } + let dmabuf_buffer_params = match udmabuf { + None => DmabufBufferParams { + size: bytes as usize, + udmabuf: None, + udmabuf_offset: 0, + udmabuf_size: 0, + udmabuf_impossible: !mem.pool().is_sealed_memfd(), + host_buffer: None, + host_buffer_impossible: !mem.pool().is_sealed_memfd(), + }, + Some((udmabuf, size)) => DmabufBufferParams { + size, + udmabuf: Some(udmabuf.clone()), + udmabuf_offset: offset, + udmabuf_size: size, + udmabuf_impossible: false, + host_buffer: None, + host_buffer_impossible: false, + }, + }; Ok(Self { id, destroyed: Cell::new(false), @@ -131,15 +149,7 @@ impl WlBuffer { dmabuf: None, render_ctx_version: Cell::new(client.state.render_ctx_version.get()), storage: RefCell::new(Some(WlBufferStorage::Shm { - dmabuf_buffer_params: DmabufBufferParams { - size: bytes as usize, - udmabuf: None, - udmabuf_offset: 0, - udmabuf_size: 0, - udmabuf_impossible: !mem.pool().is_sealed_memfd(), - host_buffer: None, - host_buffer_impossible: !mem.pool().is_sealed_memfd(), - }, + dmabuf_buffer_params, mem, stride, })), @@ -194,9 +204,9 @@ impl WlBuffer { }; let had_texture = match s { WlBufferStorage::Shm { - mem, dmabuf_buffer_params: DmabufBufferParams { + udmabuf_impossible, host_buffer, host_buffer_impossible, .. @@ -204,7 +214,7 @@ impl WlBuffer { .. } => { host_buffer.take(); - *host_buffer_impossible = !mem.pool().is_sealed_memfd(); + *host_buffer_impossible = *udmabuf_impossible; return match surface { Some(s) => { s.shm_staging.take(); @@ -310,14 +320,15 @@ impl WlBuffer { } } }; - let hb = match ctx.create_dmabuf_buffer(&udmabuf, *udmabuf_offset, *udmabuf_size) { - Ok(hb) => hb, - Err(e) => { - *host_buffer_impossible = true; - log::debug!("Could not create gfx host buffer: {}", ErrorFmt(e)); - return Ok(None); - } - }; + let hb = + match ctx.create_dmabuf_buffer(&udmabuf, *udmabuf_offset, *udmabuf_size, self.format) { + Ok(hb) => hb, + Err(e) => { + *host_buffer_impossible = true; + log::debug!("Could not create gfx host buffer: {}", ErrorFmt(e)); + return Ok(None); + } + }; *host_buffer = Some(hb.clone()); Ok(Some(hb)) } @@ -407,8 +418,6 @@ pub enum WlBufferError { GfxError(#[from] GfxError), #[error(transparent)] ClientError(Box), - #[error("Buffer format {0} is not supported for shm buffers")] - UnsupportedShmFormat(&'static str), } efrom!(WlBufferError, ClientMemError); efrom!(WlBufferError, ClientError); diff --git a/src/ifs/wl_shm.rs b/src/ifs/wl_shm.rs index 93774566..ffd1ea47 100644 --- a/src/ifs/wl_shm.rs +++ b/src/ifs/wl_shm.rs @@ -1,7 +1,6 @@ use { crate::{ client::{Client, ClientError}, - format::FORMATS, globals::{Global, GlobalName}, ifs::wl_shm_pool::{WlShmPool, WlShmPoolError}, leaks::Tracker, @@ -44,12 +43,14 @@ impl WlShmGlobal { }); track!(client, obj); client.add_client_obj(&obj)?; - for format in FORMATS { - if format.shm_info.is_some() { - client.event(Format { - self_id: id, - format: format.wl_id.unwrap_or(format.drm), - }); + if let Some(ctx) = client.state.render_ctx.get() { + for format in ctx.formats().values() { + if format.supports_shm { + client.event(Format { + self_id: id, + format: format.format.wl_id.unwrap_or(format.format.drm), + }); + } } } Ok(()) diff --git a/src/ifs/wl_shm_pool.rs b/src/ifs/wl_shm_pool.rs index 9c10c5d2..8b343f3c 100644 --- a/src/ifs/wl_shm_pool.rs +++ b/src/ifs/wl_shm_pool.rs @@ -40,6 +40,7 @@ impl WlShmPool { false, Some(client), Some(&client.state.cpu_worker), + false, )?)), fd, tracker: Default::default(), @@ -53,10 +54,9 @@ impl WlShmPoolRequestHandler for WlShmPool { fn create_buffer(&self, req: CreateBuffer, _slf: &Rc) -> Result<(), Self::Error> { let drm_format = map_wayland_format_id(req.format); - let format = match formats().get(&drm_format) { - Some(f) if f.shm_info.is_some() => *f, - _ => return Err(WlShmPoolError::InvalidFormat(req.format)), - }; + let format = formats() + .get(&drm_format) + .ok_or(WlShmPoolError::InvalidFormat(req.format))?; if req.height < 0 || req.width < 0 || req.stride < 0 || req.offset < 0 { return Err(WlShmPoolError::NegativeParameters); } @@ -69,6 +69,7 @@ impl WlShmPoolRequestHandler for WlShmPool { req.stride, format, &self.mem.get(), + None, )?); track!(self.client, buffer); self.client.add_client_obj(&buffer)?; @@ -93,6 +94,7 @@ impl WlShmPoolRequestHandler for WlShmPool { false, Some(&self.client), Some(&self.client.state.cpu_worker), + false, )?)); Ok(()) } diff --git a/src/ifs/zwp_linux_buffer_params_v1.rs b/src/ifs/zwp_linux_buffer_params_v1.rs index e91794d3..801d258e 100644 --- a/src/ifs/zwp_linux_buffer_params_v1.rs +++ b/src/ifs/zwp_linux_buffer_params_v1.rs @@ -1,8 +1,12 @@ use { crate::{ client::ClientError, + clientmem::{ClientMem, ClientMemError}, gfx_api::GfxError, - ifs::{wl_buffer::WlBuffer, zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1}, + ifs::{ + wl_buffer::{WlBuffer, WlBufferError}, + zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, + }, leaks::Tracker, object::Object, utils::{errorfmt::ErrorFmt, hash_map_ext::HashMapExt}, @@ -102,25 +106,52 @@ impl ZwpLinuxBufferParamsV1 { fd: p.fd, }); } - let img = ctx.dmabuf_img(&dmabuf)?; - let (is_client_id, buffer_id) = match buffer_id { - Some(i) => (true, i), - None => (false, self.parent.client.new_id()?), + let get_id = || match buffer_id { + None => self.parent.client.new_id(), + Some(i) => Ok(i), + }; + let buffer = if format.supports_shm + && let Some(size) = dmabuf.udmabuf_size() + { + let p = &dmabuf.planes[0]; + let client_mem = ClientMem::new( + &p.fd, + size, + true, + Some(&self.parent.client), + Some(&self.parent.client.state.cpu_worker), + true, + ) + .map(Rc::new) + .map_err(ZwpLinuxBufferParamsV1Error::CreateClientMem)?; + Rc::new(WlBuffer::new_shm( + get_id()?, + &self.parent.client, + p.offset as usize, + dmabuf.width, + dmabuf.height, + p.stride as _, + format.format, + &client_mem, + Some((&p.fd, size)), + )?) + } else { + let img = ctx.dmabuf_img(&dmabuf)?; + Rc::new(WlBuffer::new_dmabuf( + get_id()?, + &self.parent.client, + format.format, + dmabuf, + &img, + )) }; - let buffer = Rc::new(WlBuffer::new_dmabuf( - buffer_id, - &self.parent.client, - format.format, - dmabuf, - &img, - )); track!(self.parent.client, buffer); - if is_client_id { + if buffer_id.is_some() { self.parent.client.add_client_obj(&buffer)?; } else { self.parent.client.add_server_obj(&buffer); } - Ok(buffer_id) + Ok(buffer.id) } } @@ -218,5 +249,10 @@ pub enum ZwpLinuxBufferParamsV1Error { MissingPlane(usize), #[error("Could not import the buffer")] ImportError(#[from] GfxError), + #[error("Could not create ClientMem")] + CreateClientMem(#[source] ClientMemError), + #[error(transparent)] + WlBufferError(Box), } efrom!(ZwpLinuxBufferParamsV1Error, ClientError); +efrom!(ZwpLinuxBufferParamsV1Error, WlBufferError); diff --git a/src/it/test_gfx_api.rs b/src/it/test_gfx_api.rs index ecbfdc10..8e5a1865 100644 --- a/src/it/test_gfx_api.rs +++ b/src/it/test_gfx_api.rs @@ -77,6 +77,7 @@ impl TestGfxCtx { ) }) .collect(), + supports_shm: true, }, ); } diff --git a/src/it/tests/t0001_shm_formats.rs b/src/it/tests/t0001_shm_formats.rs index 26117aa6..09785f43 100644 --- a/src/it/tests/t0001_shm_formats.rs +++ b/src/it/tests/t0001_shm_formats.rs @@ -10,6 +10,7 @@ testcase!(); /// Test that wl_shm supports the required formats async fn test(run: Rc) -> Result<(), TestError> { + run.backend.install_render_context(false)?; let client = run.create_client().await?; let formats = client.shm.formats().await; tassert!(formats.contains(&XRGB8888.wl_id.unwrap())); diff --git a/src/text.rs b/src/text.rs index 752e2913..f05f1e82 100644 --- a/src/text.rs +++ b/src/text.rs @@ -2,7 +2,7 @@ use { crate::{ cmm::cmm_eotf::Eotf, cpu_worker::{AsyncCpuWork, CpuJob, CpuWork, CpuWorker, PendingJob}, - format::ARGB8888, + format::{ARGB8888, Format}, gfx_api::{ AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxBuffer, GfxContext, GfxError, GfxStagingBuffer, GfxTexture, PendingShmTransfer, STAGING_UPLOAD, @@ -125,7 +125,8 @@ struct Data { layout: PangoLayout, } -const FORMAT: CairoFormat = CAIRO_FORMAT_ARGB32; +const CAIRO_FORMAT: CairoFormat = CAIRO_FORMAT_ARGB32; +const FORMAT: &Format = ARGB8888; fn create_data( memfd: &Memfd, @@ -134,12 +135,12 @@ fn create_data( height: i32, scale: Option, ) -> Result { - let Some((stride, size)) = cairo_size(FORMAT, width, height) else { + let Some((stride, size)) = cairo_size(CAIRO_FORMAT, width, height) else { return Err(TextError::SizeOverflow); }; let data = memfd.get_pointer_for_size(size)?; let image = match unsafe { - CairoImageSurface::new_image_surface_with_data(FORMAT, data, width, height, stride) + CairoImageSurface::new_image_surface_with_data(CAIRO_FORMAT, data, width, height, stride) } { Ok(s) => s, Err(e) => return Err(TextError::CreateImage(e)), @@ -397,7 +398,7 @@ impl Shared { break 'res None; } }; - match self.ctx.create_dmabuf_buffer(&dmabuf, 0, size) { + match self.ctx.create_dmabuf_buffer(&dmabuf, 0, size, FORMAT) { Ok(b) => Some(b), Err(e) => { log::debug!("Could not create GfxBuffer: {}", ErrorFmt(e)); @@ -604,7 +605,7 @@ impl CpuJob for RenderJob { return; } if let Some(t) = &tex - && !t.compatible_with(ARGB8888, rt.width, rt.height, rt.stride) + && !t.compatible_with(FORMAT, rt.width, rt.height, rt.stride) { tex = None; } @@ -614,7 +615,7 @@ impl CpuJob for RenderJob { let tex = data .ctx .clone() - .async_shmem_texture(ARGB8888, rt.width, rt.height, rt.stride, &data.cpu_worker) + .async_shmem_texture(FORMAT, rt.width, rt.height, rt.stride, &data.cpu_worker) .map_err(TextError::CreateTexture); match tex { Ok(t) => t, diff --git a/src/udmabuf.rs b/src/udmabuf.rs index a5a76409..e991378a 100644 --- a/src/udmabuf.rs +++ b/src/udmabuf.rs @@ -30,8 +30,6 @@ pub enum UdmabufError { Open(#[source] OsError), #[error("Only the linear modifier can be allocated")] Modifier, - #[error("Format {0} is not supported")] - Format(&'static str), #[error("Could not create a memfd")] Memfd(#[source] OsError), #[error("Size calculation overflowed")] @@ -131,16 +129,13 @@ impl Allocator for Udmabuf { if !modifiers.contains(&LINEAR_MODIFIER) { return Err(UdmabufError::Modifier.into()); } - let Some(shm_info) = &format.shm_info else { - return Err(UdmabufError::Format(format.name).into()); - }; let height = height as u64; let width = width as u64; if height > 1 << 16 || width > 1 << 16 { return Err(UdmabufError::Overflow.into()); } let stride_mask = 255; - let stride = (width * shm_info.bpp as u64 + stride_mask) & !stride_mask; + let stride = (width * format.bpp as u64 + stride_mask) & !stride_mask; let size_mask = page_size() as u64 - 1; let size = (height * stride + size_mask) & !size_mask; let memfd = match uapi::memfd_create("udmabuf", MFD_ALLOW_SEALING) { @@ -186,9 +181,6 @@ impl Allocator for Udmabuf { return Err(UdmabufError::Modifier.into()); } let plane = &dmabuf.planes[0]; - let Some(shm_info) = &dmabuf.format.shm_info else { - return Err(UdmabufError::Format(dmabuf.format.name).into()); - }; let height = dmabuf.height as u64; let width = dmabuf.width as u64; let stride = plane.stride as u64; @@ -196,7 +188,7 @@ impl Allocator for Udmabuf { if height > 1 << 16 || width > 1 << 16 { return Err(UdmabufError::Overflow.into()); } - if stride < width * shm_info.bpp as u64 { + if stride < width * dmabuf.format.bpp as u64 { return Err(UdmabufError::Stride.into()); } let size = offset + stride * height; diff --git a/src/video/dmabuf.rs b/src/video/dmabuf.rs index f16bba9d..2991d5d8 100644 --- a/src/video/dmabuf.rs +++ b/src/video/dmabuf.rs @@ -2,11 +2,15 @@ use { crate::{ format::Format, utils::{compat::IoctlNumber, oserror::OsError}, - video::Modifier, + video::{LINEAR_MODIFIER, Modifier}, }, arrayvec::ArrayVec, - std::rc::Rc, - uapi::{_IOW, _IOWR, OwnedFd, c::ioctl}, + std::{rc::Rc, sync::OnceLock}, + uapi::{ + _IOW, _IOWR, OwnedFd, + c::{self, dev_t, ioctl}, + format_ustr, + }, }; #[derive(Clone, Debug)] @@ -53,6 +57,46 @@ impl DmaBuf { false } + pub fn udmabuf_size(&self) -> Option { + if self.planes.len() != 1 { + return None; + } + if self.modifier != LINEAR_MODIFIER { + return None; + } + let stat = match uapi::fstat(self.planes[0].fd.raw()) { + Ok(s) => s, + _ => return None, + }; + static DMABUF_DEV: OnceLock = OnceLock::new(); + match DMABUF_DEV.get() { + Some(d) => { + if stat.st_dev != *d { + return None; + } + } + None => { + if dma_buf_export_sync_file(&self.planes[0].fd, DMA_BUF_SYNC_READ).is_err() { + return None; + } + let _ = DMABUF_DEV.set(stat.st_dev); + } + } + let path = format_ustr!("/sys/kernel/dmabuf/buffers/{}/exporter_name", stat.st_ino); + let Ok(file) = uapi::open(path, c::O_RDONLY, 0) else { + return None; + }; + const MARKER: &[u8] = b"udmabuf\n"; + let mut buf = [0u8; MARKER.len()]; + if uapi::read(file.raw(), &mut buf).is_err() { + return None; + } + if buf != MARKER { + return None; + } + Some(stat.st_size as usize) + } + pub fn import_sync_file(&self, flags: u32, sync_file: &OwnedFd) -> Result<(), OsError> { for plane in &self.planes { dma_buf_import_sync_file(&plane.fd, flags, sync_file)?; diff --git a/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs b/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs index 0938a3ea..83c8d84c 100644 --- a/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs +++ b/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs @@ -80,6 +80,7 @@ impl JayRenderCtxEventHandler for UsrJayRenderCtx { format, read_modifiers: Default::default(), write_modifiers: Default::default(), + supports_shm: false, }, ); }