diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index f53f49e710..76c7cd1a40 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -943,6 +943,8 @@ struct WaitListEntry_t bool mangoapp_nudge; uint64_t commitID; uint64_t desiredPresentTime; + struct wlr_render_timeline wait_timeline; + uint64_t wait_point; }; sem waitListSem; @@ -982,12 +984,27 @@ void imageWaitThreadMain( void ) assert( bFound == true ); + int timeout_ms = 100; + gpuvis_trace_begin_ctx_printf( entry.commitID, "wait fence" ); - struct pollfd fd = { entry.fence, POLLIN, 0 }; - int ret = poll( &fd, 1, 100 ); - if ( ret < 0 ) + if (entry.wait_point != 0) { - xwm_log.errorf_errno( "failed to poll fence FD" ); + uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT; + uint64_t timeout_ns = (uint64_t)timeout_ms * 1000 * 1000; + int ret = drmSyncobjTimelineWait(entry.wait_timeline.drm_fd, &entry.wait_timeline.handle, &entry.wait_point, 1, timeout_ns, flags, nullptr); + if (ret < 0) + { + xwm_log.errorf("failed to wait timeline point"); + } + } + else + { + struct pollfd fd = { entry.fence, POLLIN, 0 }; + int ret = poll( &fd, 1, timeout_ms ); + if ( ret < 0 ) + { + xwm_log.errorf_errno( "failed to poll fence FD" ); + } } gpuvis_trace_end_ctx_printf( entry.commitID, "wait fence" ); diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 5692eefee9..eb336bb1c5 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -33,6 +33,7 @@ extern "C" { #include #include #include +#include #undef static #undef class } @@ -113,9 +114,18 @@ void gamescope_xwayland_server_t::wayland_commit(struct wlr_surface *surf, struc .present_id = wl_surf->present_id, .desired_present_time = wl_surf->desired_present_time, }; + + auto sync_v2_state = wlr_linux_explicit_sync_v2_get_surface_state(wlserver.wlr.explicit_sync_v2, surf); + if (sync_v2_state != nullptr) + { + newEntry.wait_timeline = *sync_v2_state->acquire_timeline; + newEntry.wait_point = sync_v2_state->acquire_point; + } + wl_surf->present_id = std::nullopt; wl_surf->desired_present_time = 0; wl_surf->pending_presentation_feedbacks.clear(); + wayland_commit_queue.push_back( newEntry ); } @@ -1458,6 +1468,9 @@ bool wlserver_init( void ) { create_presentation_time(); + int drm_fd = wlr_renderer_get_drm_fd(wlserver.wlr.renderer); + wlserver.wlr.explicit_sync_v2 = wlr_linux_explicit_sync_v2_create(wlserver.display, drm_fd); + wlserver.xdg_shell = wlr_xdg_shell_create(wlserver.display, 3); if (!wlserver.xdg_shell) { diff --git a/src/wlserver.hpp b/src/wlserver.hpp index 07f36d6140..904100d901 100644 --- a/src/wlserver.hpp +++ b/src/wlserver.hpp @@ -21,6 +21,12 @@ struct _XDisplay; struct xwayland_ctx_t; +// TODO: add getter for timeline handle +struct wlr_render_timeline { + int drm_fd; + uint32_t handle; +}; + struct wlserver_vk_swapchain_feedback { uint32_t image_count; @@ -42,6 +48,8 @@ struct ResListEntry_t { std::vector presentation_feedbacks; std::optional present_id; uint64_t desired_present_time; + struct wlr_render_timeline wait_timeline; + uint64_t wait_point; }; struct wlserver_content_override; @@ -106,6 +114,7 @@ struct wlserver_t { struct wlr_compositor *compositor; struct wlr_session *session; struct wlr_seat *seat; + struct wlr_linux_explicit_sync_v2 *explicit_sync_v2; // Used to simulate key events and set the keymap struct wlr_keyboard *virtual_keyboard_device;