Skip to content

Commit

Permalink
WIP linux-drm-syncobj-v1
Browse files Browse the repository at this point in the history
  • Loading branch information
ids1024 committed May 23, 2024
1 parent fb44b24 commit e1a602f
Show file tree
Hide file tree
Showing 11 changed files with 680 additions and 20 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
26 changes: 26 additions & 0 deletions anvil/src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::cell::RefCell;
#[cfg(feature = "xwayland")]
use smithay::xwayland::{X11Wm, XWaylandClientData};

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

fn new_surface(&mut self, surface: &WlSurface) {
add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| {
#[cfg(feature = "udev")]
let mut acquire_point = None;
let maybe_dmabuf = with_states(surface, |surface_data| {
#[cfg(feature = "udev")]
acquire_point.clone_from(
&surface_data
.cached_state
.pending::<DrmSyncobjCachedState>()
.acquire_point,
);
surface_data
.cached_state
.pending::<SurfaceAttributes>()
Expand All @@ -124,6 +135,21 @@ impl<BackendData: Backend> CompositorHandler for AnvilState<BackendData> {
})
});
if let Some(dmabuf) = maybe_dmabuf {
#[cfg(feature = "udev")]
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
26 changes: 22 additions & 4 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ use smithay::{
drm_lease::{
DrmLease, DrmLeaseBuilder, DrmLeaseHandler, DrmLeaseRequest, DrmLeaseState, LeaseRejected,
},
drm_syncobj::{DrmSyncobjHandler, DrmSyncobjState},
},
};
use smithay_drm_extras::{
Expand Down Expand Up @@ -123,9 +124,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 @@ -537,6 +538,20 @@ impl DrmLeaseHandler for AnvilState<UdevData> {

delegate_drm_lease!(AnvilState<UdevData>);

impl DrmSyncobjHandler for AnvilState<UdevData> {
fn import_device(&self) -> &smithay::backend::drm::DrmDeviceFd {
self.backend_data.backends[&self
.backend_data
.primary_gpu
.node_with_type(smithay::backend::drm::NodeType::Primary)
.unwrap()
.unwrap()]
.drm
.device_fd()
}
}
smithay::delegate_drm_syncobj!(AnvilState<UdevData>);

pub type RenderSurface = GbmBufferedSurface<GbmAllocator<DrmDeviceFd>, Option<OutputPresentationFeedback>>;

pub type GbmDrmCompositor = DrmCompositor<
Expand Down Expand Up @@ -727,13 +742,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 Expand Up @@ -860,6 +875,9 @@ impl AnvilState<UdevData> {
.add_node(render_node, gbm.clone())
.map_err(DeviceAddError::AddNode)?;

// TODO only expose if main device supports drm_syncobj_eventfd?
DrmSyncobjState::new::<Self>(&self.display_handle);

self.backend_data.backends.insert(
node,
BackendData {
Expand Down
11 changes: 10 additions & 1 deletion src/backend/drm/compositor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,15 @@ enum ScanoutBuffer<B: Buffer> {
Cursor(GbmBuffer),
}

impl<B: Buffer> ScanoutBuffer<B> {
fn acquire_point(&self) -> Option<SyncPoint> {
if let Self::Wayland(buffer) = self {
return buffer.acquire_point().cloned().map(SyncPoint::from);
}
None
}
}

impl<B: Buffer> ScanoutBuffer<B> {
#[inline]
fn from_underlying_storage(storage: UnderlyingStorage<'_>) -> Option<Self> {
Expand Down Expand Up @@ -3947,7 +3956,7 @@ where
buffer: element_config.buffer.clone(),
damage_clips,
plane_claim,
sync: None,
sync: element_config.buffer.buffer.acquire_point().map(|p| (p, None)),
};

let is_compatible = previous_state
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
48 changes: 36 additions & 12 deletions src/backend/renderer/utils/wayland.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[cfg(feature = "backend_drm")]
use crate::wayland::drm_syncobj::{DrmSyncPoint, DrmSyncobjCachedState};
use crate::{
backend::renderer::{buffer_dimensions, buffer_has_alpha, element::RenderElement, ImportAll, Renderer},
utils::{Buffer as BufferCoord, Coordinate, Logical, Physical, Point, Rectangle, Scale, Size, Transform},
Expand Down Expand Up @@ -50,12 +52,24 @@ pub struct RendererSurfaceState {
}

#[derive(Debug)]
struct InnerBuffer(WlBuffer);
struct InnerBuffer {
buffer: WlBuffer,
#[cfg(feature = "backend_drm")]
acquire_point: Option<DrmSyncPoint>,
#[cfg(feature = "backend_drm")]
release_point: Option<DrmSyncPoint>,
}

impl Drop for InnerBuffer {
#[inline]
fn drop(&mut self) {
self.0.release();
self.buffer.release();
#[cfg(feature = "backend_drm")]
if let Some(release_point) = &self.release_point {
if let Err(err) = release_point.signal() {
tracing::error!("Failed to signal syncobj release point: {}", err);
}
}
}
}

Expand All @@ -65,12 +79,11 @@ pub struct Buffer {
inner: Arc<InnerBuffer>,
}

impl From<WlBuffer> for Buffer {
#[inline]
fn from(buffer: WlBuffer) -> Self {
Buffer {
inner: Arc::new(InnerBuffer(buffer)),
}
impl Buffer {
#[cfg(feature = "backend_drm")]
#[allow(dead_code)]
pub(crate) fn acquire_point(&self) -> Option<&DrmSyncPoint> {
self.inner.acquire_point.as_ref()
}
}

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

#[inline]
fn deref(&self) -> &Self::Target {
&self.inner.0
&self.inner.buffer
}
}

impl PartialEq<WlBuffer> for Buffer {
#[inline]
fn eq(&self, other: &WlBuffer) -> bool {
self.inner.0 == *other
self.inner.buffer == *other
}
}

impl PartialEq<WlBuffer> for &Buffer {
#[inline]
fn eq(&self, other: &WlBuffer) -> bool {
self.inner.0 == *other
self.inner.buffer == *other
}
}

impl RendererSurfaceState {
#[profiling::function]
pub(crate) fn update_buffer(&mut self, states: &SurfaceData) {
#[cfg(feature = "backend_drm")]
let mut syncobj_state = states.cached_state.current::<DrmSyncobjCachedState>();

let mut attrs = states.cached_state.current::<SurfaceAttributes>();
self.buffer_delta = attrs.buffer_delta.take();

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

if !self.buffer.as_ref().map_or(false, |b| b == buffer) {
self.buffer = Some(Buffer::from(buffer));
self.buffer = Some(Buffer {
inner: Arc::new(InnerBuffer {
buffer,
#[cfg(feature = "backend_drm")]
acquire_point: syncobj_state.acquire_point.take(),
#[cfg(feature = "backend_drm")]
release_point: syncobj_state.release_point.take(),
}),
});
}

self.textures.clear();
Expand Down
24 changes: 24 additions & 0 deletions src/wayland/compositor/tree.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[cfg(feature = "backend_drm")]
use crate::wayland::drm_syncobj::DrmSyncobjCachedState;
use crate::{utils::Serial, wayland::compositor::SUBSURFACE_ROLE};

use super::{
Expand Down Expand Up @@ -156,6 +158,28 @@ impl PrivateSurfaceData {
{
buffer.release();
};
#[cfg(feature = "backend_drm")]
if let Some(release_point) = &my_data
.public_data
.cached_state
.pending::<DrmSyncobjCachedState>()
.release_point
{
if let Err(err) = release_point.signal() {
tracing::error!("Failed to signal syncobj release point: {}", err);
}
}
#[cfg(feature = "backend_drm")]
if let Some(release_point) = &my_data
.public_data
.cached_state
.current::<DrmSyncobjCachedState>()
.release_point
{
if let Err(err) = release_point.signal() {
tracing::error!("Failed to signal syncobj release point: {}", err);
}
}

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

0 comments on commit e1a602f

Please sign in to comment.