Skip to content

Commit 2fb6a6d

Browse files
committed
WIP linux-drm-syncobj-v1
Store drm device in `DrmTimeline`; destroy timeline on drop WIP OUT_FENCE_FD; always signalled in fence DRM git rev Remove patch for drm
1 parent f7638e8 commit 2fb6a6d

File tree

15 files changed

+624
-30
lines changed

15 files changed

+624
-30
lines changed

Cargo.toml

+19
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,25 @@ profiling = "1.0"
6969
smallvec = "1.11"
7070
pixman = { version = "0.1.0", features = ["drm-fourcc"], optional = true }
7171

72+
[patch.crates-io]
73+
wayland-egl = { git = "https://github.com/smithay/wayland-rs" }
74+
wayland-protocols = { git = "https://github.com/smithay/wayland-rs" }
75+
wayland-protocols-wlr = { git = "https://github.com/smithay/wayland-rs" }
76+
wayland-protocols-misc = { git = "https://github.com/smithay/wayland-rs" }
77+
wayland-server = { git = "https://github.com/smithay/wayland-rs" }
78+
wayland-client = { git = "https://github.com/smithay/wayland-rs" }
79+
wayland-sys = { git = "https://github.com/smithay/wayland-rs" }
80+
wayland-backend = { git = "https://github.com/smithay/wayland-rs" }
81+
wayland-scanner = { git = "https://github.com/smithay/wayland-rs" }
82+
# wayland-egl = { path = "../wayland-rs/wayland-egl/" }
83+
# wayland-protocols = { path = "../wayland-rs/wayland-protocols/" }
84+
# wayland-protocols-wlr = { path = "../wayland-rs/wayland-protocols-wlr/" }
85+
# wayland-protocols-misc = { path = "../wayland-rs/wayland-protocols-misc/" }
86+
# wayland-server = { path = "../wayland-rs/wayland-server/" }
87+
# wayland-client = { path = "../wayland-rs/wayland-client/" }
88+
# wayland-sys = { path = "../wayland-rs/wayland-sys/" }
89+
# wayland-backend = { path = "../wayland-rs/wayland-backend/" }
90+
# wayland-scanner = { path = "../wayland-rs/wayland-scanner/" }
7291

7392
[dev-dependencies]
7493
clap = { version = "4", features = ["derive"] }

anvil/src/shell/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use smithay::{
2626
CompositorState, SurfaceAttributes, TraversalAction,
2727
},
2828
dmabuf::get_dmabuf,
29+
drm_syncobj::DrmSyncobjCachedState,
2930
shell::{
3031
wlr_layer::{
3132
Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler,
@@ -112,7 +113,13 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {
112113

113114
fn new_surface(&mut self, surface: &WlSurface) {
114115
add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| {
116+
let mut acquire_point = None;
115117
let maybe_dmabuf = with_states(surface, |surface_data| {
118+
acquire_point = surface_data
119+
.cached_state
120+
.pending::<DrmSyncobjCachedState>()
121+
.acquire_point
122+
.clone();
116123
surface_data
117124
.cached_state
118125
.pending::<SurfaceAttributes>()
@@ -124,6 +131,20 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {
124131
})
125132
});
126133
if let Some(dmabuf) = maybe_dmabuf {
134+
if let Some(acquire_point) = acquire_point {
135+
if let Ok((blocker, source)) = acquire_point.generate_blocker() {
136+
let client = surface.client().unwrap();
137+
let res = state.handle.insert_source(source, move |_, _, data| {
138+
let dh = data.display_handle.clone();
139+
data.client_compositor_state(&client).blocker_cleared(data, &dh);
140+
Ok(())
141+
});
142+
if res.is_ok() {
143+
add_blocker(surface, blocker);
144+
return;
145+
}
146+
}
147+
}
127148
if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {
128149
if let Some(client) = surface.client() {
129150
let res = state.handle.insert_source(source, move |_, _, data| {

anvil/src/state.rs

+29-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
any::Any,
23
os::unix::io::OwnedFd,
34
sync::{atomic::AtomicBool, Arc},
45
time::Duration,
@@ -13,12 +14,13 @@ use smithay::{
1314
default_primary_scanout_output_compare, utils::select_dmabuf_feedback, RenderElementStates,
1415
},
1516
},
16-
delegate_compositor, delegate_data_control, delegate_data_device, delegate_fractional_scale,
17-
delegate_input_method_manager, delegate_keyboard_shortcuts_inhibit, delegate_layer_shell,
18-
delegate_output, delegate_pointer_constraints, delegate_pointer_gestures, delegate_presentation,
19-
delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_security_context,
20-
delegate_shm, delegate_tablet_manager, delegate_text_input_manager, delegate_viewporter,
21-
delegate_virtual_keyboard_manager, delegate_xdg_activation, delegate_xdg_decoration, delegate_xdg_shell,
17+
delegate_compositor, delegate_data_control, delegate_data_device, delegate_drm_syncobj,
18+
delegate_fractional_scale, delegate_input_method_manager, delegate_keyboard_shortcuts_inhibit,
19+
delegate_layer_shell, delegate_output, delegate_pointer_constraints, delegate_pointer_gestures,
20+
delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat,
21+
delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_text_input_manager,
22+
delegate_viewporter, delegate_virtual_keyboard_manager, delegate_xdg_activation, delegate_xdg_decoration,
23+
delegate_xdg_shell,
2224
desktop::{
2325
space::SpaceElement,
2426
utils::{
@@ -48,6 +50,7 @@ use smithay::{
4850
wayland::{
4951
compositor::{get_parent, with_states, CompositorClientState, CompositorState},
5052
dmabuf::DmabufFeedback,
53+
drm_syncobj::{DrmSyncobjHandler, DrmSyncobjState},
5154
fractional_scale::{with_fractional_scale, FractionalScaleHandler, FractionalScaleManagerState},
5255
input_method::{InputMethodHandler, InputMethodManagerState, PopupSurface},
5356
keyboard_shortcuts_inhibit::{
@@ -532,6 +535,22 @@ impl<BackendData: Backend> XdgForeignHandler for AnvilState<BackendData> {
532535
}
533536
smithay::delegate_xdg_foreign!(@<BackendData: Backend + 'static> AnvilState<BackendData>);
534537

538+
impl<BackendData: Backend> DrmSyncobjHandler for AnvilState<BackendData> {
539+
fn import_device(&self) -> &smithay::backend::drm::DrmDeviceFd {
540+
let udev_data = &<dyn Any>::downcast_ref::<AnvilState<crate::udev::UdevData>>(self)
541+
.expect("syncobj protocol used on backend other than DRM")
542+
.backend_data;
543+
udev_data.backends[&udev_data
544+
.primary_gpu
545+
.node_with_type(smithay::backend::drm::NodeType::Primary)
546+
.unwrap()
547+
.unwrap()]
548+
.drm
549+
.device_fd()
550+
}
551+
}
552+
delegate_drm_syncobj!(@<BackendData: Backend + 'static> AnvilState<BackendData>);
553+
535554
impl<BackendData: Backend + 'static> AnvilState<BackendData> {
536555
pub fn init(
537556
display: Display<AnvilState<BackendData>>,
@@ -610,6 +629,10 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
610629
.get_data::<ClientState>()
611630
.map_or(true, |client_state| client_state.security_context.is_none())
612631
});
632+
if <dyn Any>::downcast_ref::<AnvilState<crate::udev::UdevData>>(&backend_data).is_some() {
633+
// TODO only expose if main device supports drm_syncobj_eventfd?
634+
DrmSyncobjState::new::<Self>(&dh);
635+
}
613636

614637
// init input
615638
let seat_name = backend_data.seat_name();

anvil/src/udev.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ pub struct UdevData {
123123
pub session: LibSeatSession,
124124
dh: DisplayHandle,
125125
dmabuf_state: Option<(DmabufState, DmabufGlobal)>,
126-
primary_gpu: DrmNode,
126+
pub primary_gpu: DrmNode,
127127
gpus: GpuManager<GbmGlesBackend<GlesRenderer, DrmDeviceFd>>,
128-
backends: HashMap<DrmNode, BackendData>,
128+
pub backends: HashMap<DrmNode, BackendData>,
129129
pointer_images: Vec<(xcursor::parser::Image, MemoryRenderBuffer)>,
130130
pointer_element: PointerElement,
131131
#[cfg(feature = "debug")]
@@ -727,13 +727,13 @@ impl Drop for SurfaceData {
727727
}
728728
}
729729

730-
struct BackendData {
730+
pub struct BackendData {
731731
surfaces: HashMap<crtc::Handle, SurfaceData>,
732732
non_desktop_connectors: Vec<(connector::Handle, crtc::Handle)>,
733733
leasing_global: Option<DrmLeaseState>,
734734
active_leases: Vec<DrmLease>,
735735
gbm: GbmDevice<DrmDeviceFd>,
736-
drm: DrmDevice,
736+
pub drm: DrmDevice,
737737
drm_scanner: DrmScanner,
738738
render_node: DrmNode,
739739
registration_token: RegistrationToken,

src/backend/drm/compositor/mod.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,14 @@ use std::{
124124
collections::{HashMap, HashSet},
125125
fmt::Debug,
126126
io::ErrorKind,
127-
os::unix::io::{AsFd, OwnedFd},
127+
os::unix::io::{AsFd, BorrowedFd, OwnedFd},
128128
rc::Rc,
129129
sync::{Arc, Mutex},
130130
};
131131

132132
use ::gbm::{BufferObject, BufferObjectFlags};
133133
use drm::{
134-
control::{connector, crtc, framebuffer, plane, Mode, PlaneType},
134+
control::{connector, crtc, Device as _, framebuffer, plane, Mode, PlaneType},
135135
Device, DriverCapability,
136136
};
137137
use drm_fourcc::{DrmFormat, DrmFourcc, DrmModifier};
@@ -634,7 +634,7 @@ impl<B: Framebuffer> FrameState<B> {
634634
let backup = current_config.clone();
635635
*current_config = state;
636636

637-
let res = surface.test_state(self.build_planes(surface, supports_fencing, true), allow_modeset);
637+
let res = surface.test_state(self.build_planes(surface, supports_fencing, true, None), allow_modeset);
638638

639639
if res.is_err() {
640640
// test failed, restore previous state
@@ -674,7 +674,7 @@ impl<B: Framebuffer> FrameState<B> {
674674
}
675675

676676
let res = surface.test_state(
677-
self.build_planes(surface, supports_fencing, allow_partial_update),
677+
self.build_planes(surface, supports_fencing, allow_partial_update, None),
678678
allow_modeset,
679679
);
680680

@@ -694,11 +694,14 @@ impl<B: Framebuffer> FrameState<B> {
694694
supports_fencing: bool,
695695
allow_partial_update: bool,
696696
event: bool,
697+
out_fence_fd: &mut Option<OwnedFd>,
698+
signalled_sync_file: Option<BorrowedFd<'_>>, // XXX
697699
) -> Result<(), crate::backend::drm::error::Error> {
698700
debug_assert!(!self.planes.iter().any(|(_, state)| state.needs_test));
699701
surface.commit(
700-
self.build_planes(surface, supports_fencing, allow_partial_update),
702+
self.build_planes(surface, supports_fencing, allow_partial_update, signalled_sync_file),
701703
event,
704+
Some(out_fence_fd),
702705
)
703706
}
704707

@@ -709,11 +712,14 @@ impl<B: Framebuffer> FrameState<B> {
709712
supports_fencing: bool,
710713
allow_partial_update: bool,
711714
event: bool,
715+
out_fence_fd: &mut Option<OwnedFd>,
716+
signalled_sync_file: Option<BorrowedFd<'_>>, // XXX
712717
) -> Result<(), crate::backend::drm::error::Error> {
713718
debug_assert!(!self.planes.iter().any(|(_, state)| state.needs_test));
714719
surface.page_flip(
715-
self.build_planes(surface, supports_fencing, allow_partial_update),
720+
self.build_planes(surface, supports_fencing, allow_partial_update, signalled_sync_file),
716721
event,
722+
Some(out_fence_fd)
717723
)
718724
}
719725

@@ -723,6 +729,7 @@ impl<B: Framebuffer> FrameState<B> {
723729
surface: &'a DrmSurface,
724730
supports_fencing: bool,
725731
allow_partial_update: bool,
732+
signalled_sync_file: Option<BorrowedFd<'a>>, // XXX
726733
) -> impl IntoIterator<Item = super::PlaneState<'a>> {
727734
for (_, state) in self.planes.iter_mut().filter(|(_, state)| !state.skip) {
728735
if let Some(config) = state.config.as_mut() {
@@ -759,10 +766,14 @@ impl<B: Framebuffer> FrameState<B> {
759766
transform: config.properties.transform,
760767
damage_clips: config.damage_clips.as_ref().map(|d| d.blob()),
761768
fb: *config.buffer.as_ref(),
769+
// XXX
770+
fence: signalled_sync_file
771+
/*
762772
fence: config
763773
.sync
764774
.as_ref()
765775
.and_then(|(_, fence)| fence.as_ref().map(|fence| fence.as_fd())),
776+
*/
766777
}),
767778
})
768779
}
@@ -1514,6 +1525,8 @@ where
15141525

15151526
debug_flags: DebugFlags,
15161527
span: tracing::Span,
1528+
1529+
signalled_sync_file: Option<OwnedFd>,
15171530
}
15181531

15191532
impl<A, F, U, G> DrmCompositor<A, F, U, G>
@@ -1600,6 +1613,14 @@ where
16001613
})?
16011614
&& plane_has_property(&*surface, surface.plane(), "IN_FENCE_FD")?;
16021615

1616+
let mut signalled_sync_file = None;
1617+
if supports_fencing {
1618+
// XXX unwrap
1619+
let syncobj = surface.device_fd().create_syncobj(true).unwrap();
1620+
signalled_sync_file = Some(surface.device_fd().syncobj_to_fd(syncobj, true).unwrap());
1621+
surface.device_fd().destroy_syncobj(syncobj).unwrap();
1622+
}
1623+
16031624
for format in color_formats {
16041625
debug!("Testing color format: {}", format);
16051626
match Self::find_supported_format(
@@ -1663,6 +1684,7 @@ where
16631684
supports_fencing,
16641685
debug_flags: DebugFlags::empty(),
16651686
span,
1687+
signalled_sync_file,
16661688
};
16671689

16681690
return Ok(drm_renderer);
@@ -2558,16 +2580,20 @@ where
25582580
} = self.queued_frame.take().unwrap();
25592581

25602582
let allow_partial_update = prepared_frame.kind == PreparedFrameKind::Partial;
2583+
let mut out_fence_fd = None;
2584+
let signalled_sync_file = self.signalled_sync_file.as_ref().map(|x| x.as_fd());
25612585
let flip = if self.surface.commit_pending() {
25622586
prepared_frame
25632587
.frame
2564-
.commit(&self.surface, self.supports_fencing, allow_partial_update, true)
2588+
.commit(&self.surface, self.supports_fencing, allow_partial_update, true, &mut out_fence_fd, signalled_sync_file)
25652589
} else {
25662590
prepared_frame
25672591
.frame
2568-
.page_flip(&self.surface, self.supports_fencing, allow_partial_update, true)
2592+
.page_flip(&self.surface, self.supports_fencing, allow_partial_update, true, &mut out_fence_fd, signalled_sync_file)
25692593
};
25702594

2595+
dbg!(out_fence_fd);
2596+
25712597
match flip {
25722598
Ok(_) => {
25732599
if prepared_frame.kind == PreparedFrameKind::Full {

src/backend/drm/device/fd.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use tracing::{error, info, warn};
77

88
use crate::utils::{DevPath, DeviceFd};
99

10-
#[derive(Debug)]
10+
#[derive(Debug, PartialEq)]
1111
struct InternalDrmDeviceFd {
1212
fd: DeviceFd,
1313
privileged: bool,
@@ -33,7 +33,7 @@ impl BasicDevice for InternalDrmDeviceFd {}
3333
impl ControlDevice for InternalDrmDeviceFd {}
3434

3535
/// Ref-counted file descriptor of an open drm device
36-
#[derive(Debug, Clone)]
36+
#[derive(Debug, Clone, PartialEq)]
3737
pub struct DrmDeviceFd(Arc<InternalDrmDeviceFd>);
3838

3939
impl AsFd for DrmDeviceFd {

0 commit comments

Comments
 (0)