Skip to content

Commit df603ff

Browse files
committed
WIP linux-drm-syncobj-v1
1 parent 96af9cb commit df603ff

File tree

9 files changed

+660
-19
lines changed

9 files changed

+660
-19
lines changed

anvil/src/shell/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::cell::RefCell;
33
#[cfg(feature = "xwayland")]
44
use smithay::xwayland::{X11Wm, XWaylandClientData};
55

6+
#[cfg(feature = "udev")]
7+
use smithay::wayland::drm_syncobj::DrmSyncobjCachedState;
68
use smithay::{
79
backend::renderer::utils::on_commit_buffer_handler,
810
desktop::{
@@ -112,7 +114,16 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {
112114

113115
fn new_surface(&mut self, surface: &WlSurface) {
114116
add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| {
117+
#[cfg(feature = "udev")]
118+
let mut acquire_point = None;
115119
let maybe_dmabuf = with_states(surface, |surface_data| {
120+
#[cfg(feature = "udev")]
121+
acquire_point.clone_from(
122+
&surface_data
123+
.cached_state
124+
.pending::<DrmSyncobjCachedState>()
125+
.acquire_point,
126+
);
116127
surface_data
117128
.cached_state
118129
.pending::<SurfaceAttributes>()
@@ -124,6 +135,21 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {
124135
})
125136
});
126137
if let Some(dmabuf) = maybe_dmabuf {
138+
#[cfg(feature = "udev")]
139+
if let Some(acquire_point) = acquire_point {
140+
if let Ok((blocker, source)) = acquire_point.generate_blocker() {
141+
let client = surface.client().unwrap();
142+
let res = state.handle.insert_source(source, move |_, _, data| {
143+
let dh = data.display_handle.clone();
144+
data.client_compositor_state(&client).blocker_cleared(data, &dh);
145+
Ok(())
146+
});
147+
if res.is_ok() {
148+
add_blocker(surface, blocker);
149+
return;
150+
}
151+
}
152+
}
127153
if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {
128154
if let Some(client) = surface.client() {
129155
let res = state.handle.insert_source(source, move |_, _, data| {

anvil/src/udev.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ use smithay::{
8484
drm_lease::{
8585
DrmLease, DrmLeaseBuilder, DrmLeaseHandler, DrmLeaseRequest, DrmLeaseState, LeaseRejected,
8686
},
87+
drm_syncobj::{DrmSyncobjHandler, DrmSyncobjState},
8788
},
8889
};
8990
use smithay_drm_extras::{
@@ -123,9 +124,9 @@ pub struct UdevData {
123124
pub session: LibSeatSession,
124125
dh: DisplayHandle,
125126
dmabuf_state: Option<(DmabufState, DmabufGlobal)>,
126-
primary_gpu: DrmNode,
127+
pub primary_gpu: DrmNode,
127128
gpus: GpuManager<GbmGlesBackend<GlesRenderer, DrmDeviceFd>>,
128-
backends: HashMap<DrmNode, BackendData>,
129+
pub backends: HashMap<DrmNode, BackendData>,
129130
pointer_images: Vec<(xcursor::parser::Image, MemoryRenderBuffer)>,
130131
pointer_element: PointerElement,
131132
#[cfg(feature = "debug")]
@@ -537,6 +538,20 @@ impl DrmLeaseHandler for AnvilState<UdevData> {
537538

538539
delegate_drm_lease!(AnvilState<UdevData>);
539540

541+
impl DrmSyncobjHandler for AnvilState<UdevData> {
542+
fn import_device(&self) -> &smithay::backend::drm::DrmDeviceFd {
543+
self.backend_data.backends[&self
544+
.backend_data
545+
.primary_gpu
546+
.node_with_type(smithay::backend::drm::NodeType::Primary)
547+
.unwrap()
548+
.unwrap()]
549+
.drm
550+
.device_fd()
551+
}
552+
}
553+
smithay::delegate_drm_syncobj!(AnvilState<UdevData>);
554+
540555
pub type RenderSurface = GbmBufferedSurface<GbmAllocator<DrmDeviceFd>, Option<OutputPresentationFeedback>>;
541556

542557
pub type GbmDrmCompositor = DrmCompositor<
@@ -727,13 +742,13 @@ impl Drop for SurfaceData {
727742
}
728743
}
729744

730-
struct BackendData {
745+
pub struct BackendData {
731746
surfaces: HashMap<crtc::Handle, SurfaceData>,
732747
non_desktop_connectors: Vec<(connector::Handle, crtc::Handle)>,
733748
leasing_global: Option<DrmLeaseState>,
734749
active_leases: Vec<DrmLease>,
735750
gbm: GbmDevice<DrmDeviceFd>,
736-
drm: DrmDevice,
751+
pub drm: DrmDevice,
737752
drm_scanner: DrmScanner,
738753
render_node: DrmNode,
739754
registration_token: RegistrationToken,
@@ -860,6 +875,9 @@ impl AnvilState<UdevData> {
860875
.add_node(render_node, gbm.clone())
861876
.map_err(DeviceAddError::AddNode)?;
862877

878+
// TODO only expose if main device supports drm_syncobj_eventfd?
879+
DrmSyncobjState::new::<Self>(&self.display_handle);
880+
863881
self.backend_data.backends.insert(
864882
node,
865883
BackendData {

src/backend/drm/compositor/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,15 @@ enum ScanoutBuffer<B: Buffer> {
203203
Cursor(GbmBuffer),
204204
}
205205

206+
impl<B: Buffer> ScanoutBuffer<B> {
207+
fn acquire_point(&self) -> Option<SyncPoint> {
208+
if let Self::Wayland(buffer) = self {
209+
return buffer.acquire_point().cloned().map(SyncPoint::from);
210+
}
211+
None
212+
}
213+
}
214+
206215
impl<B: Buffer> ScanoutBuffer<B> {
207216
#[inline]
208217
fn from_underlying_storage(storage: UnderlyingStorage<'_>) -> Option<Self> {
@@ -3947,7 +3956,7 @@ where
39473956
buffer: element_config.buffer.clone(),
39483957
damage_clips,
39493958
plane_claim,
3950-
sync: None,
3959+
sync: element_config.buffer.buffer.acquire_point().map(|p| (p, None)),
39513960
};
39523961

39533962
let is_compatible = previous_state

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 {

src/backend/renderer/utils/wayland.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(feature = "backend_drm")]
2+
use crate::wayland::drm_syncobj::{DrmSyncPoint, DrmSyncobjCachedState};
13
use crate::{
24
backend::renderer::{buffer_dimensions, buffer_has_alpha, element::RenderElement, ImportAll, Renderer},
35
utils::{Buffer as BufferCoord, Coordinate, Logical, Physical, Point, Rectangle, Scale, Size, Transform},
@@ -50,12 +52,24 @@ pub struct RendererSurfaceState {
5052
}
5153

5254
#[derive(Debug)]
53-
struct InnerBuffer(WlBuffer);
55+
struct InnerBuffer {
56+
buffer: WlBuffer,
57+
#[cfg(feature = "backend_drm")]
58+
acquire_point: Option<DrmSyncPoint>,
59+
#[cfg(feature = "backend_drm")]
60+
release_point: Option<DrmSyncPoint>,
61+
}
5462

5563
impl Drop for InnerBuffer {
5664
#[inline]
5765
fn drop(&mut self) {
58-
self.0.release();
66+
self.buffer.release();
67+
#[cfg(feature = "backend_drm")]
68+
if let Some(release_point) = &self.release_point {
69+
if let Err(err) = release_point.signal() {
70+
tracing::error!("Failed to signal syncobj release point: {}", err);
71+
}
72+
}
5973
}
6074
}
6175

@@ -65,12 +79,11 @@ pub struct Buffer {
6579
inner: Arc<InnerBuffer>,
6680
}
6781

68-
impl From<WlBuffer> for Buffer {
69-
#[inline]
70-
fn from(buffer: WlBuffer) -> Self {
71-
Buffer {
72-
inner: Arc::new(InnerBuffer(buffer)),
73-
}
82+
impl Buffer {
83+
#[cfg(feature = "backend_drm")]
84+
#[allow(dead_code)]
85+
pub(crate) fn acquire_point(&self) -> Option<&DrmSyncPoint> {
86+
self.inner.acquire_point.as_ref()
7487
}
7588
}
7689

@@ -79,27 +92,30 @@ impl std::ops::Deref for Buffer {
7992

8093
#[inline]
8194
fn deref(&self) -> &Self::Target {
82-
&self.inner.0
95+
&self.inner.buffer
8396
}
8497
}
8598

8699
impl PartialEq<WlBuffer> for Buffer {
87100
#[inline]
88101
fn eq(&self, other: &WlBuffer) -> bool {
89-
self.inner.0 == *other
102+
self.inner.buffer == *other
90103
}
91104
}
92105

93106
impl PartialEq<WlBuffer> for &Buffer {
94107
#[inline]
95108
fn eq(&self, other: &WlBuffer) -> bool {
96-
self.inner.0 == *other
109+
self.inner.buffer == *other
97110
}
98111
}
99112

100113
impl RendererSurfaceState {
101114
#[profiling::function]
102115
pub(crate) fn update_buffer(&mut self, states: &SurfaceData) {
116+
#[cfg(feature = "backend_drm")]
117+
let mut syncobj_state = states.cached_state.current::<DrmSyncobjCachedState>();
118+
103119
let mut attrs = states.cached_state.current::<SurfaceAttributes>();
104120
self.buffer_delta = attrs.buffer_delta.take();
105121

@@ -122,7 +138,15 @@ impl RendererSurfaceState {
122138
self.buffer_transform = attrs.buffer_transform.into();
123139

124140
if !self.buffer.as_ref().map_or(false, |b| b == buffer) {
125-
self.buffer = Some(Buffer::from(buffer));
141+
self.buffer = Some(Buffer {
142+
inner: Arc::new(InnerBuffer {
143+
buffer,
144+
#[cfg(feature = "backend_drm")]
145+
acquire_point: syncobj_state.acquire_point.take(),
146+
#[cfg(feature = "backend_drm")]
147+
release_point: syncobj_state.release_point.take(),
148+
}),
149+
});
126150
}
127151

128152
self.textures.clear();

src/wayland/compositor/tree.rs

+24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(feature = "backend_drm")]
2+
use crate::wayland::drm_syncobj::DrmSyncobjCachedState;
13
use crate::{utils::Serial, wayland::compositor::SUBSURFACE_ROLE};
24

35
use super::{
@@ -156,6 +158,28 @@ impl PrivateSurfaceData {
156158
{
157159
buffer.release();
158160
};
161+
#[cfg(feature = "backend_drm")]
162+
if let Some(release_point) = &my_data
163+
.public_data
164+
.cached_state
165+
.pending::<DrmSyncobjCachedState>()
166+
.release_point
167+
{
168+
if let Err(err) = release_point.signal() {
169+
tracing::error!("Failed to signal syncobj release point: {}", err);
170+
}
171+
}
172+
#[cfg(feature = "backend_drm")]
173+
if let Some(release_point) = &my_data
174+
.public_data
175+
.cached_state
176+
.current::<DrmSyncobjCachedState>()
177+
.release_point
178+
{
179+
if let Err(err) = release_point.signal() {
180+
tracing::error!("Failed to signal syncobj release point: {}", err);
181+
}
182+
}
159183

160184
let hooks = my_data.destruction_hooks.clone();
161185
// don't hold the mutex while the hooks are invoked

0 commit comments

Comments
 (0)