Skip to content

Commit

Permalink
WIP linux-drm-syncobj-v1
Browse files Browse the repository at this point in the history
Store drm device in `DrmTimeline`; destroy timeline on drop

WIP OUT_FENCE_FD; always signalled in fence

DRM git rev

Remove patch for drm
  • Loading branch information
ids1024 committed May 13, 2024
1 parent f7638e8 commit fbb5ca6
Show file tree
Hide file tree
Showing 15 changed files with 654 additions and 38 deletions.
19 changes: 19 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ profiling = "1.0"
smallvec = "1.11"
pixman = { version = "0.1.0", features = ["drm-fourcc"], optional = true }

[patch.crates-io]
wayland-egl = { git = "https://github.com/smithay/wayland-rs" }
wayland-protocols = { git = "https://github.com/smithay/wayland-rs" }
wayland-protocols-wlr = { git = "https://github.com/smithay/wayland-rs" }
wayland-protocols-misc = { git = "https://github.com/smithay/wayland-rs" }
wayland-server = { git = "https://github.com/smithay/wayland-rs" }
wayland-client = { git = "https://github.com/smithay/wayland-rs" }
wayland-sys = { git = "https://github.com/smithay/wayland-rs" }
wayland-backend = { git = "https://github.com/smithay/wayland-rs" }
wayland-scanner = { git = "https://github.com/smithay/wayland-rs" }
# wayland-egl = { path = "../wayland-rs/wayland-egl/" }
# wayland-protocols = { path = "../wayland-rs/wayland-protocols/" }
# wayland-protocols-wlr = { path = "../wayland-rs/wayland-protocols-wlr/" }
# wayland-protocols-misc = { path = "../wayland-rs/wayland-protocols-misc/" }
# wayland-server = { path = "../wayland-rs/wayland-server/" }
# wayland-client = { path = "../wayland-rs/wayland-client/" }
# wayland-sys = { path = "../wayland-rs/wayland-sys/" }
# wayland-backend = { path = "../wayland-rs/wayland-backend/" }
# wayland-scanner = { path = "../wayland-rs/wayland-scanner/" }

[dev-dependencies]
clap = { version = "4", features = ["derive"] }
Expand Down
21 changes: 21 additions & 0 deletions anvil/src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use smithay::{
CompositorState, SurfaceAttributes, TraversalAction,
},
dmabuf::get_dmabuf,
drm_syncobj::DrmSyncobjCachedState,
shell::{
wlr_layer::{
Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler,
Expand Down Expand Up @@ -112,7 +113,13 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {

fn new_surface(&mut self, surface: &WlSurface) {
add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| {
let mut acquire_point = None;
let maybe_dmabuf = with_states(surface, |surface_data| {
acquire_point = surface_data
.cached_state
.pending::<DrmSyncobjCachedState>()
.acquire_point
.clone();
surface_data
.cached_state
.pending::<SurfaceAttributes>()
Expand All @@ -124,6 +131,20 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {
})
});
if let Some(dmabuf) = maybe_dmabuf {
if let Some(acquire_point) = acquire_point {
if let Ok((blocker, source)) = acquire_point.generate_blocker() {
let client = surface.client().unwrap();
let res = state.handle.insert_source(source, move |_, _, data| {
let dh = data.display_handle.clone();
data.client_compositor_state(&client).blocker_cleared(data, &dh);
Ok(())
});
if res.is_ok() {
add_blocker(surface, blocker);
return;
}
}
}
if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {
if let Some(client) = surface.client() {
let res = state.handle.insert_source(source, move |_, _, data| {
Expand Down
35 changes: 29 additions & 6 deletions anvil/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{
any::Any,
os::unix::io::OwnedFd,
sync::{atomic::AtomicBool, Arc},
time::Duration,
Expand All @@ -13,12 +14,13 @@ use smithay::{
default_primary_scanout_output_compare, utils::select_dmabuf_feedback, RenderElementStates,
},
},
delegate_compositor, delegate_data_control, delegate_data_device, delegate_fractional_scale,
delegate_input_method_manager, delegate_keyboard_shortcuts_inhibit, delegate_layer_shell,
delegate_output, delegate_pointer_constraints, delegate_pointer_gestures, delegate_presentation,
delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_security_context,
delegate_shm, delegate_tablet_manager, delegate_text_input_manager, delegate_viewporter,
delegate_virtual_keyboard_manager, delegate_xdg_activation, delegate_xdg_decoration, delegate_xdg_shell,
delegate_compositor, delegate_data_control, delegate_data_device, delegate_drm_syncobj,
delegate_fractional_scale, delegate_input_method_manager, delegate_keyboard_shortcuts_inhibit,
delegate_layer_shell, delegate_output, delegate_pointer_constraints, delegate_pointer_gestures,
delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat,
delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_text_input_manager,
delegate_viewporter, delegate_virtual_keyboard_manager, delegate_xdg_activation, delegate_xdg_decoration,
delegate_xdg_shell,
desktop::{
space::SpaceElement,
utils::{
Expand Down Expand Up @@ -48,6 +50,7 @@ use smithay::{
wayland::{
compositor::{get_parent, with_states, CompositorClientState, CompositorState},
dmabuf::DmabufFeedback,
drm_syncobj::{DrmSyncobjHandler, DrmSyncobjState},
fractional_scale::{with_fractional_scale, FractionalScaleHandler, FractionalScaleManagerState},
input_method::{InputMethodHandler, InputMethodManagerState, PopupSurface},
keyboard_shortcuts_inhibit::{
Expand Down Expand Up @@ -532,6 +535,22 @@ impl<BackendData: Backend> XdgForeignHandler for AnvilState<BackendData> {
}
smithay::delegate_xdg_foreign!(@<BackendData: Backend + 'static> AnvilState<BackendData>);

impl<BackendData: Backend> DrmSyncobjHandler for AnvilState<BackendData> {
fn import_device(&self) -> &smithay::backend::drm::DrmDeviceFd {
let udev_data = &<dyn Any>::downcast_ref::<AnvilState<crate::udev::UdevData>>(self)
.expect("syncobj protocol used on backend other than DRM")
.backend_data;
udev_data.backends[&udev_data
.primary_gpu
.node_with_type(smithay::backend::drm::NodeType::Primary)
.unwrap()
.unwrap()]
.drm
.device_fd()
}
}
delegate_drm_syncobj!(@<BackendData: Backend + 'static> AnvilState<BackendData>);

impl<BackendData: Backend + 'static> AnvilState<BackendData> {
pub fn init(
display: Display<AnvilState<BackendData>>,
Expand Down Expand Up @@ -610,6 +629,10 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
.get_data::<ClientState>()
.map_or(true, |client_state| client_state.security_context.is_none())
});
if <dyn Any>::downcast_ref::<AnvilState<crate::udev::UdevData>>(&backend_data).is_some() {
// TODO only expose if main device supports drm_syncobj_eventfd?
DrmSyncobjState::new::<Self>(&dh);
}

// init input
let seat_name = backend_data.seat_name();
Expand Down
8 changes: 4 additions & 4 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ pub struct UdevData {
pub session: LibSeatSession,
dh: DisplayHandle,
dmabuf_state: Option<(DmabufState, DmabufGlobal)>,
primary_gpu: DrmNode,
pub primary_gpu: DrmNode,
gpus: GpuManager<GbmGlesBackend<GlesRenderer, DrmDeviceFd>>,
backends: HashMap<DrmNode, BackendData>,
pub backends: HashMap<DrmNode, BackendData>,
pointer_images: Vec<(xcursor::parser::Image, MemoryRenderBuffer)>,
pointer_element: PointerElement,
#[cfg(feature = "debug")]
Expand Down Expand Up @@ -727,13 +727,13 @@ impl Drop for SurfaceData {
}
}

struct BackendData {
pub struct BackendData {
surfaces: HashMap<crtc::Handle, SurfaceData>,
non_desktop_connectors: Vec<(connector::Handle, crtc::Handle)>,
leasing_global: Option<DrmLeaseState>,
active_leases: Vec<DrmLease>,
gbm: GbmDevice<DrmDeviceFd>,
drm: DrmDevice,
pub drm: DrmDevice,
drm_scanner: DrmScanner,
render_node: DrmNode,
registration_token: RegistrationToken,
Expand Down
80 changes: 64 additions & 16 deletions src/backend/drm/compositor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ use std::{
collections::{HashMap, HashSet},
fmt::Debug,
io::ErrorKind,
os::unix::io::{AsFd, OwnedFd},
os::unix::io::{AsFd, BorrowedFd, OwnedFd},
rc::Rc,
sync::{Arc, Mutex},
};

use ::gbm::{BufferObject, BufferObjectFlags};
use drm::{
control::{connector, crtc, framebuffer, plane, Mode, PlaneType},
control::{connector, crtc, framebuffer, plane, Device as _, Mode, PlaneType},
Device, DriverCapability,
};
use drm_fourcc::{DrmFormat, DrmFourcc, DrmModifier};
Expand Down Expand Up @@ -634,7 +634,10 @@ impl<B: Framebuffer> FrameState<B> {
let backup = current_config.clone();
*current_config = state;

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

if res.is_err() {
// test failed, restore previous state
Expand Down Expand Up @@ -674,7 +677,7 @@ impl<B: Framebuffer> FrameState<B> {
}

let res = surface.test_state(
self.build_planes(surface, supports_fencing, allow_partial_update),
self.build_planes(surface, supports_fencing, allow_partial_update, None),
allow_modeset,
);

Expand All @@ -694,11 +697,19 @@ impl<B: Framebuffer> FrameState<B> {
supports_fencing: bool,
allow_partial_update: bool,
event: bool,
out_fence_fd: &mut Option<OwnedFd>,
signalled_sync_file: Option<BorrowedFd<'_>>, // XXX
) -> Result<(), crate::backend::drm::error::Error> {
debug_assert!(!self.planes.iter().any(|(_, state)| state.needs_test));
surface.commit(
self.build_planes(surface, supports_fencing, allow_partial_update),
self.build_planes(
surface,
supports_fencing,
allow_partial_update,
signalled_sync_file,
),
event,
Some(out_fence_fd),
)
}

Expand All @@ -709,11 +720,19 @@ impl<B: Framebuffer> FrameState<B> {
supports_fencing: bool,
allow_partial_update: bool,
event: bool,
out_fence_fd: &mut Option<OwnedFd>,
signalled_sync_file: Option<BorrowedFd<'_>>, // XXX
) -> Result<(), crate::backend::drm::error::Error> {
debug_assert!(!self.planes.iter().any(|(_, state)| state.needs_test));
surface.page_flip(
self.build_planes(surface, supports_fencing, allow_partial_update),
self.build_planes(
surface,
supports_fencing,
allow_partial_update,
signalled_sync_file,
),
event,
Some(out_fence_fd),
)
}

Expand All @@ -723,6 +742,7 @@ impl<B: Framebuffer> FrameState<B> {
surface: &'a DrmSurface,
supports_fencing: bool,
allow_partial_update: bool,
signalled_sync_file: Option<BorrowedFd<'a>>, // XXX
) -> impl IntoIterator<Item = super::PlaneState<'a>> {
for (_, state) in self.planes.iter_mut().filter(|(_, state)| !state.skip) {
if let Some(config) = state.config.as_mut() {
Expand Down Expand Up @@ -759,10 +779,13 @@ impl<B: Framebuffer> FrameState<B> {
transform: config.properties.transform,
damage_clips: config.damage_clips.as_ref().map(|d| d.blob()),
fb: *config.buffer.as_ref(),
fence: config
.sync
.as_ref()
.and_then(|(_, fence)| fence.as_ref().map(|fence| fence.as_fd())),
// XXX
fence: signalled_sync_file, /*
fence: config
.sync
.as_ref()
.and_then(|(_, fence)| fence.as_ref().map(|fence| fence.as_fd())),
*/
}),
})
}
Expand Down Expand Up @@ -1514,6 +1537,8 @@ where

debug_flags: DebugFlags,
span: tracing::Span,

signalled_sync_file: Option<OwnedFd>,
}

impl<A, F, U, G> DrmCompositor<A, F, U, G>
Expand Down Expand Up @@ -1600,6 +1625,14 @@ where
})?
&& plane_has_property(&*surface, surface.plane(), "IN_FENCE_FD")?;

let mut signalled_sync_file = None;
if supports_fencing {
// XXX unwrap
let syncobj = surface.device_fd().create_syncobj(true).unwrap();
signalled_sync_file = Some(surface.device_fd().syncobj_to_fd(syncobj, true).unwrap());
surface.device_fd().destroy_syncobj(syncobj).unwrap();
}

for format in color_formats {
debug!("Testing color format: {}", format);
match Self::find_supported_format(
Expand Down Expand Up @@ -1663,6 +1696,7 @@ where
supports_fencing,
debug_flags: DebugFlags::empty(),
span,
signalled_sync_file,
};

return Ok(drm_renderer);
Expand Down Expand Up @@ -2558,16 +2592,30 @@ where
} = self.queued_frame.take().unwrap();

let allow_partial_update = prepared_frame.kind == PreparedFrameKind::Partial;
let mut out_fence_fd = None;
let signalled_sync_file = self.signalled_sync_file.as_ref().map(|x| x.as_fd());
let flip = if self.surface.commit_pending() {
prepared_frame
.frame
.commit(&self.surface, self.supports_fencing, allow_partial_update, true)
prepared_frame.frame.commit(
&self.surface,
self.supports_fencing,
allow_partial_update,
true,
&mut out_fence_fd,
signalled_sync_file,
)
} else {
prepared_frame
.frame
.page_flip(&self.surface, self.supports_fencing, allow_partial_update, true)
prepared_frame.frame.page_flip(
&self.surface,
self.supports_fencing,
allow_partial_update,
true,
&mut out_fence_fd,
signalled_sync_file,
)
};

dbg!(out_fence_fd);

match flip {
Ok(_) => {
if prepared_frame.kind == PreparedFrameKind::Full {
Expand Down
4 changes: 2 additions & 2 deletions src/backend/drm/device/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tracing::{error, info, warn};

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

#[derive(Debug)]
#[derive(Debug, PartialEq)]
struct InternalDrmDeviceFd {
fd: DeviceFd,
privileged: bool,
Expand All @@ -33,7 +33,7 @@ impl BasicDevice for InternalDrmDeviceFd {}
impl ControlDevice for InternalDrmDeviceFd {}

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

impl AsFd for DrmDeviceFd {
Expand Down
Loading

0 comments on commit fbb5ca6

Please sign in to comment.