From a1985b2870f61d5da08df97fce903523cd805679 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 10 Sep 2024 14:29:44 +0200 Subject: [PATCH] metal: disable implicit sync in KMS --- src/backends/metal.rs | 4 +++- src/backends/metal/present.rs | 12 ++++++++---- src/backends/metal/video.rs | 12 ++++++++++++ src/video/drm/sync_obj.rs | 18 +++++++++++++++++- src/video/drm/sys.rs | 4 ++-- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/backends/metal.rs b/src/backends/metal.rs index 0d2765e2..759e60f5 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -16,7 +16,7 @@ use { }, dbus::{DbusError, SignalHandler}, drm_feedback::DrmFeedback, - gfx_api::GfxError, + gfx_api::{GfxError, SyncFile}, ifs::{ wl_output::OutputId, wl_seat::tablet::{ @@ -150,6 +150,7 @@ pub struct MetalBackend { pause_handler: Cell>, resume_handler: Cell>, ctx: CloneCell>>, + signaled_sync_file: CloneCell>, default_feedback: CloneCell>>, persistent_display_data: CopyHashMap, Rc>, } @@ -324,6 +325,7 @@ pub async fn create(state: &Rc) -> Result, MetalError> { pause_handler: Default::default(), resume_handler: Default::default(), ctx: Default::default(), + signaled_sync_file: Default::default(), default_feedback: Default::default(), persistent_display_data: Default::default(), }); diff --git a/src/backends/metal/present.rs b/src/backends/metal/present.rs index aa26e838..d7e0bfa6 100644 --- a/src/backends/metal/present.rs +++ b/src/backends/metal/present.rs @@ -292,7 +292,9 @@ impl MetalConnector { change!(c, plane.crtc_w, crtc_w); change!(c, plane.crtc_h, crtc_h); if !try_async_flip && !self.dev.is_nvidia { - c.change(plane.in_fence_fd, -1i32 as u64); + if let Some(sf) = self.backend.signaled_sync_file.get() { + c.change(plane.in_fence_fd, sf.0.raw() as u64); + } } }); } else { @@ -329,7 +331,9 @@ impl MetalConnector { c.change(plane.src_w.id, (*width as u64) << 16); c.change(plane.src_h.id, (*height as u64) << 16); if !self.dev.is_nvidia { - c.change(plane.in_fence_fd, -1i32 as u64); + if let Some(sf) = self.backend.signaled_sync_file.get() { + c.change(plane.in_fence_fd, sf.0.raw() as u64); + } } }); } @@ -512,8 +516,8 @@ impl MetalConnector { } ct }; - if let AcquireSync::None = ct.acquire_sync { - // Cannot perform scanout without sync. + if let AcquireSync::None | AcquireSync::Implicit = ct.acquire_sync { + // Cannot perform scanout without explicit sync. return None; } if ct.source.buffer_transform != ct.target.output_transform { diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 6895a7e9..79aa6470 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -2029,6 +2029,18 @@ impl MetalBackend { } } let ctx = dev.ctx.get(); + if self.signaled_sync_file.is_none() { + if let Some(sync) = ctx.gfx.sync_obj_ctx() { + match sync.create_signaled_sync_file() { + Ok(sf) => { + self.signaled_sync_file.set(Some(sf)); + } + Err(e) => { + log::warn!("Could not create signaled sync file: {}", ErrorFmt(e)); + } + } + } + } self.state.set_render_ctx(Some(ctx.gfx.clone())); let fb = match DrmFeedback::new(&self.state.drm_feedback_ids, &*ctx.gfx) { Ok(fb) => Some(Rc::new(fb)), diff --git a/src/video/drm/sync_obj.rs b/src/video/drm/sync_obj.rs index 97de5b7a..39c1b6ec 100644 --- a/src/video/drm/sync_obj.rs +++ b/src/video/drm/sync_obj.rs @@ -13,7 +13,8 @@ use { sys::{ sync_ioc_merge, sync_obj_create, sync_obj_destroy, sync_obj_eventfd, sync_obj_fd_to_handle, sync_obj_handle_to_fd, sync_obj_signal, sync_obj_transfer, - DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, + DRM_SYNCOBJ_CREATE_SIGNALED, DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, + DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, }, DrmError, @@ -125,6 +126,21 @@ impl SyncObjCtx { Ok(sync_obj) } + pub fn create_signaled_sync_file(&self) -> Result { + let handle = sync_obj_create(self.inner.drm.raw(), DRM_SYNCOBJ_CREATE_SIGNALED) + .map_err(DrmError::CreateSyncObj)?; + let handle = SyncObjHandle(handle); + let fd = sync_obj_handle_to_fd( + self.inner.drm.raw(), + handle.0, + DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE, + ); + destroy(&self.inner.drm, handle); + fd.map_err(DrmError::ExportSyncObj) + .map(Rc::new) + .map(SyncFile) + } + pub fn wait_for_point( &self, eventfd: &OwnedFd, diff --git a/src/video/drm/sys.rs b/src/video/drm/sys.rs index 556a8ef0..225d0693 100644 --- a/src/video/drm/sys.rs +++ b/src/video/drm/sys.rs @@ -1177,7 +1177,7 @@ pub struct drm_format_modifier { unsafe impl Pod for drm_format_modifier {} -// pub const DRM_SYNCOBJ_CREATE_SIGNALED: u32 = 1 << 0; +pub const DRM_SYNCOBJ_CREATE_SIGNALED: u32 = 1 << 0; #[repr(C)] struct drm_syncobj_create { @@ -1212,7 +1212,7 @@ pub fn sync_obj_destroy(drm: c::c_int, handle: u32) -> Result<(), OsError> { } pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE: u32 = 1 << 0; -// pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1 << 0; +pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1 << 0; #[repr(C)] struct drm_syncobj_handle {