Commit e4b186dffb77
tarball3 files changed+83-2
@@ -30,6 +30,7 @@ use smithay::reexports::drm::control::{ModeTypeFlags, connector, crtc};
3030
use smithay::reexports::input::Libinput;3131
use smithay::reexports::rustix::fs::OFlags;3232
use smithay::utils::{DeviceFd, Point, Transform};33
+use smithay::wayland::drm_syncobj::{DrmSyncobjState, supports_syncobj_eventfd};3334
use smithay_drm_extras::drm_scanner::{DrmScanEvent, DrmScanner};3435
use std::collections::{HashMap, VecDeque};3536
use std::path::{Path, PathBuf};@@ -158,6 +159,11 @@ pub fn init(
158159
.get_driver()159160
.map(|d| d.name().to_string_lossy().to_lowercase().contains("nvidia"))160161
.unwrap_or(false);162
+ if supports_syncobj_eventfd(&fd) {163
+ state.syncobj = Some(DrmSyncobjState::new::<State>(&state.display, fd.clone()));164
+ } else {165
+ tracing::info!("no syncobj eventfd support, clients stay on implicit sync");166
+ }161167
let gbm = GbmDevice::new(fd)?;162168
let render_node = node163169
.node_with_type(NodeType::Render)@@ -6,6 +6,7 @@ use smithay::desktop::{PopupKind, Window};
66
use smithay::input::dnd::{DndGrabHandler, GrabType, Source};77
use smithay::input::pointer::CursorImageStatus;88
use smithay::input::{Seat, SeatHandler, SeatState};9
+use smithay::reexports::calloop::Interest;910
use smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer;1011
use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode as DecorationMode;1112
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;@@ -15,9 +16,14 @@ use smithay::reexports::wayland_server::{Client, Resource};
1516
use smithay::utils::Serial;1617
use smithay::wayland::buffer::BufferHandler;1718
use smithay::wayland::compositor::{18
- CompositorClientState, CompositorHandler, CompositorState, get_parent, is_sync_subsurface,19
+ BufferAssignment, CompositorClientState, CompositorHandler, CompositorState,20
+ SurfaceAttributes, add_blocker, add_pre_commit_hook, get_parent, is_sync_subsurface,21
+ with_states,22
+};23
+use smithay::wayland::drm_syncobj::{DrmSyncobjCachedState, DrmSyncobjHandler, DrmSyncobjState};24
+use smithay::wayland::dmabuf::{25
+ DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier, get_dmabuf,1926
};20
-use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier};2127
use smithay::wayland::output::OutputHandler;2228
use smithay::wayland::selection::SelectionHandler;2329
use smithay::wayland::selection::data_device::{@@ -35,6 +41,12 @@ impl CompositorHandler for State {
3541
&mut self.compositor_state3642
}3743
44
+ fn new_surface(&mut self, surface: &WlSurface) {45
+ add_pre_commit_hook::<Self, _>(surface, |state, _dh, surface| {46
+ hold_until_readable(state, surface);47
+ });48
+ }49
+3850
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {3951
&client4052
.get_data::<ClientState>()@@ -218,6 +230,67 @@ impl smithay::wayland::pointer_constraints::PointerConstraintsHandler for State
218230
219231
smithay::delegate_dispatch2!(State);220232
233
+impl DrmSyncobjHandler for State {234
+ fn drm_syncobj_state(&mut self) -> Option<&mut DrmSyncobjState> {235
+ self.syncobj.as_mut()236
+ }237
+}238
+239
+/// Holds a dmabuf commit until the buffer can be read without the renderer240
+/// stalling on the client's GPU work: until its explicit acquire point241
+/// signals, or for implicitly synced buffers until their writes finish.242
+fn hold_until_readable(state: &mut State, surface: &WlSurface) {243
+ let (acquire, dmabuf) = with_states(surface, |s| {244
+ let acquire = s245
+ .cached_state246
+ .get::<DrmSyncobjCachedState>()247
+ .pending()248
+ .acquire_point249
+ .clone();250
+ let dmabuf = match s251
+ .cached_state252
+ .get::<SurfaceAttributes>()253
+ .pending()254
+ .buffer255
+ .as_ref()256
+ {257
+ Some(BufferAssignment::NewBuffer(buffer)) => get_dmabuf(buffer).cloned().ok(),258
+ _ => None,259
+ };260
+ (acquire, dmabuf)261
+ });262
+ let (Some(dmabuf), Some(client)) = (dmabuf, surface.client()) else {263
+ return;264
+ };265
+ if let Some(point) = acquire266
+ && let Ok((blocker, source)) = point.generate_blocker()267
+ {268
+ let inserted = state.handle.insert_source(source, move |_, _, state| {269
+ let dh = state.display.clone();270
+ state271
+ .client_compositor_state(&client)272
+ .blocker_cleared(state, &dh);273
+ Ok(())274
+ });275
+ if inserted.is_ok() {276
+ add_blocker(surface, blocker);277
+ }278
+ return;279
+ }280
+ if let Ok((blocker, source)) = dmabuf.generate_blocker(Interest::READ) {281
+ let inserted = state.handle.insert_source(source, move |_, _, state| {282
+ let dh = state.display.clone();283
+ state284
+ .client_compositor_state(&client)285
+ .blocker_cleared(state, &dh);286
+ Ok(())287
+ });288
+ if inserted.is_ok() {289
+ add_blocker(surface, blocker);290
+ }291
+ }292
+}293
+221294
impl XdgDecorationHandler for State {222295
fn new_decoration(&mut self, toplevel: ToplevelSurface) {223296
server_side(&toplevel);@@ -46,6 +46,7 @@ pub struct State {
4646
pub popups: PopupManager,4747
pub host: Option<Host>,4848
pub drm: Option<crate::drm::Drm>,49
+ pub syncobj: Option<smithay::wayland::drm_syncobj::DrmSyncobjState>,4950
pub cursor: crate::cursor::Cursor,5051
pub cursor_status: CursorImageStatus,5152
pub needs_redraw: bool,@@ -145,6 +146,7 @@ impl State {
145146
popups: PopupManager::default(),146147
host: None,147148
drm: None,149
+ syncobj: None,148150
cursor: crate::cursor::Cursor::load(),149151
cursor_status: CursorImageStatus::default_named(),150152
needs_redraw: true,