xwayland: add support for wp_linux_drm_syncobj_v1
This protocol allows for explicit synchronization of GPU operations by Wayland clients and the compositor. Xwayland can make use of this to ensure any rendering it initiates has completed before the target image is accessed by the compositor, without having to rely on kernel-level implicit synchronization. Furthermore, for X11 clients that also support explicit synchronization using the mechanisms exposed in the DRI3 and Present extensions, this Wayland protocol allows us to simply forward the timeline, acquire, and release points directly to the compositor, ideally avoiding any premature stalls in the presentation pipeline. Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com> Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/967>
This commit is contained in:
parent
6f85ce4d4e
commit
87bf2cafcc
|
@ -50,6 +50,7 @@ shortcuts_inhibit_xml = join_paths(protodir, 'unstable', 'keyboard-shortcuts-inh
|
|||
xwayland_shell_xml = join_paths(protodir, 'staging', 'xwayland-shell', 'xwayland-shell-v1.xml')
|
||||
tearing_xml = join_paths(protodir, 'staging', 'tearing-control', 'tearing-control-v1.xml')
|
||||
fractional_scale_xml = join_paths(protodir, 'staging', 'fractional-scale', 'fractional-scale-v1.xml')
|
||||
syncobj_xml = join_paths(protodir, 'staging', 'linux-drm-syncobj', 'linux-drm-syncobj-v1.xml')
|
||||
|
||||
client_header = generator(scanner,
|
||||
output : '@BASENAME@-client-protocol.h',
|
||||
|
@ -80,6 +81,7 @@ srcs += client_header.process(shortcuts_inhibit_xml)
|
|||
srcs += client_header.process(xwayland_shell_xml)
|
||||
srcs += client_header.process(tearing_xml)
|
||||
srcs += client_header.process(fractional_scale_xml)
|
||||
srcs += client_header.process(syncobj_xml)
|
||||
srcs += code.process(relative_xml)
|
||||
srcs += code.process(pointer_xml)
|
||||
srcs += code.process(gestures_xml)
|
||||
|
@ -94,6 +96,7 @@ srcs += code.process(shortcuts_inhibit_xml)
|
|||
srcs += code.process(xwayland_shell_xml)
|
||||
srcs += code.process(tearing_xml)
|
||||
srcs += code.process(fractional_scale_xml)
|
||||
srcs += code.process(syncobj_xml)
|
||||
|
||||
if build_ei
|
||||
xwayland_dep += libei_dep
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "xwayland-screen.h"
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
|
||||
struct xwl_gbm_private {
|
||||
drmDevice *device;
|
||||
|
@ -620,6 +621,8 @@ xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen)
|
|||
wl_drm_destroy(xwl_gbm->drm);
|
||||
if (xwl_gbm->gbm)
|
||||
gbm_device_destroy(xwl_gbm->gbm);
|
||||
if (xwl_screen->explicit_sync)
|
||||
wp_linux_drm_syncobj_manager_v1_destroy(xwl_screen->explicit_sync);
|
||||
|
||||
free(xwl_gbm);
|
||||
}
|
||||
|
@ -965,8 +968,38 @@ struct xwl_dri3_syncobj
|
|||
{
|
||||
struct dri3_syncobj base;
|
||||
uint32_t handle;
|
||||
struct wp_linux_drm_syncobj_timeline_v1 *timeline;
|
||||
};
|
||||
|
||||
void
|
||||
xwl_glamor_dri3_syncobj_passthrough(WindowPtr window,
|
||||
struct dri3_syncobj *acquire_syncobj,
|
||||
struct dri3_syncobj *release_syncobj,
|
||||
uint64_t acquire_point,
|
||||
uint64_t release_point)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(window);
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
struct xwl_dri3_syncobj *xwl_acquire_syncobj = (struct xwl_dri3_syncobj *)acquire_syncobj;
|
||||
struct xwl_dri3_syncobj *xwl_release_syncobj = (struct xwl_dri3_syncobj *)release_syncobj;
|
||||
uint32_t acquire_hi = acquire_point >> 32;
|
||||
uint32_t acquire_lo = acquire_point & 0xffffffff;
|
||||
uint32_t release_hi = release_point >> 32;
|
||||
uint32_t release_lo = release_point & 0xffffffff;
|
||||
|
||||
if (!xwl_window->surface_sync)
|
||||
xwl_window->surface_sync =
|
||||
wp_linux_drm_syncobj_manager_v1_get_surface(xwl_screen->explicit_sync,
|
||||
xwl_window->surface);
|
||||
|
||||
wp_linux_drm_syncobj_surface_v1_set_acquire_point(xwl_window->surface_sync,
|
||||
xwl_acquire_syncobj->timeline,
|
||||
acquire_hi, acquire_lo);
|
||||
wp_linux_drm_syncobj_surface_v1_set_release_point(xwl_window->surface_sync,
|
||||
xwl_release_syncobj->timeline,
|
||||
release_hi, release_lo);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_dri3_check_syncobj(struct dri3_syncobj *syncobj, uint64_t point, Bool check_avail)
|
||||
{
|
||||
|
@ -1046,6 +1079,9 @@ xwl_dri3_free_syncobj(struct dri3_syncobj *syncobj)
|
|||
struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen);
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
|
||||
if (xwl_syncobj->timeline)
|
||||
wp_linux_drm_syncobj_timeline_v1_destroy(xwl_syncobj->timeline);
|
||||
|
||||
if (xwl_syncobj->handle)
|
||||
drmSyncobjDestroy(xwl_gbm->drm_fd, xwl_syncobj->handle);
|
||||
|
||||
|
@ -1082,10 +1118,28 @@ static struct dri3_syncobj *
|
|||
xwl_dri3_create_syncobj(struct xwl_screen *xwl_screen, uint32_t handle)
|
||||
{
|
||||
struct xwl_dri3_syncobj *syncobj = calloc(1, sizeof (*syncobj));
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
Bool create = !handle;
|
||||
|
||||
if (!syncobj)
|
||||
return NULL;
|
||||
|
||||
if (create && drmSyncobjCreate(xwl_gbm->drm_fd, 0, &handle))
|
||||
goto fail;
|
||||
|
||||
if (xwl_screen->explicit_sync) {
|
||||
int syncobj_fd = -1;
|
||||
if (drmSyncobjHandleToFD(xwl_gbm->drm_fd, handle, &syncobj_fd))
|
||||
goto fail;
|
||||
|
||||
syncobj->timeline =
|
||||
wp_linux_drm_syncobj_manager_v1_import_timeline(xwl_screen->explicit_sync,
|
||||
syncobj_fd);
|
||||
close(syncobj_fd);
|
||||
if (!syncobj->timeline)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
syncobj->handle = handle;
|
||||
syncobj->base.screen = xwl_screen->screen;
|
||||
syncobj->base.refcount = 1;
|
||||
|
@ -1099,6 +1153,18 @@ xwl_dri3_create_syncobj(struct xwl_screen *xwl_screen, uint32_t handle)
|
|||
syncobj->base.signaled_eventfd = xwl_dri3_syncobj_signaled_eventfd;
|
||||
syncobj->base.submitted_eventfd = xwl_dri3_syncobj_submitted_eventfd;
|
||||
return &syncobj->base;
|
||||
|
||||
fail:
|
||||
if (create && handle)
|
||||
drmSyncobjDestroy(xwl_gbm->drm_fd, handle);
|
||||
free(syncobj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dri3_syncobj *
|
||||
xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
return xwl_dri3_create_syncobj(xwl_screen, 0 /* allocate new handle */);
|
||||
}
|
||||
|
||||
static struct dri3_syncobj *
|
||||
|
@ -1301,6 +1367,17 @@ xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_set_syncobj_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
{
|
||||
xwl_screen->explicit_sync =
|
||||
wl_registry_bind(xwl_screen->registry, id,
|
||||
&wp_linux_drm_syncobj_manager_v1_interface,
|
||||
version);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_gbm_has_egl_extension(void)
|
||||
{
|
||||
|
@ -1545,6 +1622,12 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
|
|||
"ANDROID_native_fence_sync"))
|
||||
xwl_gbm->supports_syncobjs = TRUE;
|
||||
|
||||
if (!xwl_gbm->supports_syncobjs && xwl_screen->explicit_sync) {
|
||||
/* explicit sync requires syncobj support */
|
||||
wp_linux_drm_syncobj_manager_v1_destroy(xwl_screen->explicit_sync);
|
||||
xwl_screen->explicit_sync = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
if (xwl_screen->egl_display != EGL_NO_DISPLAY) {
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "drm-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
|
||||
#include "xwayland-dmabuf.h"
|
||||
#include "xwayland-glamor.h"
|
||||
|
@ -111,6 +112,8 @@ xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
|
|||
xwl_screen_set_drm_interface(xwl_screen, id, version);
|
||||
else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0)
|
||||
xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
|
||||
else if (strcmp(interface, wp_linux_drm_syncobj_manager_v1_interface.name) == 0)
|
||||
xwl_screen_set_syncobj_interface(xwl_screen, id, version);
|
||||
}
|
||||
|
||||
static Bool
|
||||
|
@ -293,6 +296,27 @@ xwl_glamor_get_fence(struct xwl_screen *xwl_screen)
|
|||
return fence_fd;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence_fd)
|
||||
{
|
||||
EGLint attribs[3];
|
||||
EGLSyncKHR sync;
|
||||
|
||||
if (!xwl_screen->glamor)
|
||||
return;
|
||||
|
||||
xwl_glamor_egl_make_current(xwl_screen);
|
||||
|
||||
attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
|
||||
attribs[1] = fence_fd;
|
||||
attribs[2] = EGL_NONE;
|
||||
sync = eglCreateSyncKHR(xwl_screen->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
|
||||
if (sync != EGL_NO_SYNC_KHR) {
|
||||
eglWaitSyncKHR(xwl_screen->egl_display, sync, 0);
|
||||
eglDestroySyncKHR(xwl_screen->egl_display, sync);
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_init(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-glamor-gbm.h"
|
||||
#include "dri3.h"
|
||||
|
||||
typedef enum _xwl_glamor_mode_flags{
|
||||
XWL_GLAMOR_NONE = 0,
|
||||
|
@ -49,6 +50,8 @@ Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
|
|||
|
||||
Bool xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version);
|
||||
Bool xwl_screen_set_syncobj_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version);
|
||||
struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
|
||||
void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *registry,
|
||||
|
@ -62,6 +65,13 @@ void xwl_glamor_dmabuf_import_sync_file(PixmapPtr pixmap, int sync_file);
|
|||
int xwl_glamor_dmabuf_export_sync_file(PixmapPtr pixmap);
|
||||
Bool xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen);
|
||||
int xwl_glamor_get_fence(struct xwl_screen *screen);
|
||||
void xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence);
|
||||
struct dri3_syncobj *xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen);
|
||||
void xwl_glamor_dri3_syncobj_passthrough(WindowPtr window,
|
||||
struct dri3_syncobj *acquire_syncobj,
|
||||
struct dri3_syncobj *release_syncobj,
|
||||
uint64_t acquire_point,
|
||||
uint64_t release_point);
|
||||
|
||||
#ifdef XV
|
||||
/* glamor Xv Adaptor */
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "xwayland-pixmap.h"
|
||||
|
||||
#include "tearing-control-v1-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
|
||||
#define XWL_PRESENT_CAPS PresentCapabilityAsync | PresentCapabilityAsyncMayTear
|
||||
|
||||
|
@ -389,6 +390,7 @@ static void
|
|||
xwl_present_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
|
||||
{
|
||||
WindowPtr window = vblank->window;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
uint8_t mode = PresentCompleteModeFlip;
|
||||
|
||||
|
@ -405,9 +407,14 @@ xwl_present_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t
|
|||
struct xwl_present_event *event =
|
||||
xwl_present_event_from_vblank(xwl_present_window->flip_active);
|
||||
|
||||
if (!event->pixmap)
|
||||
if (!event->pixmap
|
||||
#ifdef DRI3
|
||||
/* If this flip used explicit sync, we won't get a release event */
|
||||
|| (xwl_screen->explicit_sync && vblank->release_syncobj)
|
||||
#endif /* DRI3 */
|
||||
) {
|
||||
xwl_present_free_event(event);
|
||||
else
|
||||
} else
|
||||
/* Put the previous flip in the idle_queue and wait for further notice from
|
||||
* the Wayland compositor
|
||||
*/
|
||||
|
@ -767,7 +774,8 @@ xwl_present_check_flip(RRCrtcPtr crtc,
|
|||
!xwl_glamor_check_flip(present_window, pixmap))
|
||||
return FALSE;
|
||||
|
||||
if (!xwl_glamor_supports_implicit_sync(xwl_window->xwl_screen))
|
||||
if (!xwl_glamor_supports_implicit_sync(xwl_window->xwl_screen) &&
|
||||
!xwl_window->xwl_screen->explicit_sync)
|
||||
return FALSE;
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
|
@ -852,6 +860,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
|
|||
BoxPtr damage_box;
|
||||
struct wl_buffer *buffer;
|
||||
struct xwl_present_event *event = xwl_present_event_from_vblank(vblank);
|
||||
Bool implicit_sync = TRUE;
|
||||
|
||||
if (!xwl_window)
|
||||
return FALSE;
|
||||
|
@ -868,8 +877,34 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
|
|||
|
||||
event->pixmap = pixmap;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (vblank->acquire_syncobj && vblank->release_syncobj) {
|
||||
if (xwl_window->xwl_screen->explicit_sync) {
|
||||
xwl_glamor_dri3_syncobj_passthrough(present_window,
|
||||
vblank->acquire_syncobj,
|
||||
vblank->release_syncobj,
|
||||
vblank->acquire_point,
|
||||
vblank->release_point);
|
||||
implicit_sync = FALSE;
|
||||
} else {
|
||||
/* transfer from acquire syncobj to implicit fence */
|
||||
int fence_fd =
|
||||
vblank->acquire_syncobj->export_fence(vblank->acquire_syncobj,
|
||||
vblank->acquire_point);
|
||||
xwl_glamor_dmabuf_import_sync_file(vblank->pixmap, fence_fd);
|
||||
}
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
if (implicit_sync) {
|
||||
xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event);
|
||||
|
||||
if (xwl_window->surface_sync) {
|
||||
wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync);
|
||||
xwl_window->surface_sync = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can flip directly to the main surface (full screen window without clips) */
|
||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||
|
||||
|
@ -911,6 +946,42 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
static void
|
||||
xwl_present_acquire_fence_avail(int fd, int xevents, void *data)
|
||||
{
|
||||
present_vblank_ptr vblank = data;
|
||||
|
||||
SetNotifyFd(fd, NULL, 0, NULL);
|
||||
close(fd);
|
||||
vblank->efd = -1;
|
||||
|
||||
xwl_present_re_execute(vblank);
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
static Bool
|
||||
xwl_present_wait_acquire_fence_avail(struct xwl_screen *xwl_screen,
|
||||
present_vblank_ptr vblank)
|
||||
{
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
/* If the compositor does not support explicit sync we need to wait for the
|
||||
* acquire fence to be submitted before flipping. */
|
||||
if (vblank->flip && !xwl_screen->explicit_sync &&
|
||||
vblank->pixmap && vblank->acquire_syncobj &&
|
||||
!vblank->acquire_syncobj->has_fence(vblank->acquire_syncobj,
|
||||
vblank->acquire_point)) {
|
||||
vblank->efd = eventfd(0, EFD_CLOEXEC);
|
||||
SetNotifyFd(vblank->efd, xwl_present_acquire_fence_avail, X_NOTIFY_READ, vblank);
|
||||
vblank->acquire_syncobj->submitted_eventfd(vblank->acquire_syncobj,
|
||||
vblank->acquire_point,
|
||||
vblank->efd);
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Once the required MSC has been reached, execute the pending request.
|
||||
*
|
||||
|
@ -927,11 +998,13 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
|
|||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
|
||||
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
|
||||
struct xwl_present_event *event = xwl_present_event_from_vblank(vblank);
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
|
||||
|
||||
xorg_list_del(&vblank->event_queue);
|
||||
|
||||
retry:
|
||||
if (present_execute_wait(vblank, crtc_msc))
|
||||
if (present_execute_wait(vblank, crtc_msc) ||
|
||||
xwl_present_wait_acquire_fence_avail(xwl_screen, vblank))
|
||||
return;
|
||||
|
||||
if (flip_pending && vblank->flip && vblank->pixmap && vblank->window) {
|
||||
|
@ -967,7 +1040,6 @@ retry:
|
|||
if (xwl_present_flip(vblank, damage)) {
|
||||
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(vblank->window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(window);
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
|
||||
|
||||
/* Replace window pixmap with flip pixmap */
|
||||
|
|
|
@ -112,6 +112,7 @@ struct xwl_screen {
|
|||
struct xwayland_shell_v1 *xwayland_shell;
|
||||
struct wp_tearing_control_manager_v1 *tearing_control_manager;
|
||||
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
|
||||
struct wp_linux_drm_syncobj_manager_v1 *explicit_sync;
|
||||
struct xorg_list drm_lease_devices;
|
||||
struct xorg_list queued_drm_lease_devices;
|
||||
struct xorg_list drm_leases;
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
#ifdef XWL_HAS_GLAMOR
|
||||
#include "glamor.h"
|
||||
#endif
|
||||
#include "dri3.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
|
||||
#define BUFFER_TIMEOUT 1 * 1000 /* ms */
|
||||
|
||||
|
@ -42,6 +47,11 @@ struct xwl_window_buffer {
|
|||
struct xwl_window *xwl_window;
|
||||
PixmapPtr pixmap;
|
||||
RegionPtr damage_region;
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
struct dri3_syncobj *syncobj;
|
||||
uint64_t timeline_point;
|
||||
int efd;
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
int refcnt;
|
||||
uint32_t time;
|
||||
struct xorg_list link_buffer;
|
||||
|
@ -80,6 +90,9 @@ xwl_window_buffer_new(struct xwl_window *xwl_window)
|
|||
xwl_window_buffer->damage_region = RegionCreate(NullBox, 1);
|
||||
xwl_window_buffer->pixmap = NullPixmap;
|
||||
xwl_window_buffer->refcnt = 1;
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
xwl_window_buffer->efd = -1;
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
xorg_list_init(&xwl_window_buffer->link_buffer);
|
||||
|
||||
|
@ -109,6 +122,16 @@ xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer)
|
|||
if (xwl_window_buffer->pixmap)
|
||||
xwl_window_buffer_destroy_pixmap (xwl_window_buffer);
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_window_buffer->syncobj)
|
||||
xwl_window_buffer->syncobj->free(xwl_window_buffer->syncobj);
|
||||
|
||||
if (xwl_window_buffer->efd >= 0) {
|
||||
SetNotifyFd(xwl_window_buffer->efd, NULL, 0, NULL);
|
||||
close(xwl_window_buffer->efd);
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
xorg_list_del(&xwl_window_buffer->link_buffer);
|
||||
free(xwl_window_buffer);
|
||||
|
||||
|
@ -215,6 +238,20 @@ xwl_window_buffer_release_callback(void *data)
|
|||
xwl_window);
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
static void
|
||||
xwl_window_buffers_release_fence_avail(int fd, int xevents, void *data)
|
||||
{
|
||||
struct xwl_window_buffer *xwl_window_buffer = data;
|
||||
|
||||
SetNotifyFd(fd, NULL, 0, NULL);
|
||||
close(fd);
|
||||
xwl_window_buffer->efd = -1;
|
||||
|
||||
xwl_window_buffer_release_callback(data);
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
void
|
||||
xwl_window_buffers_init(struct xwl_window *xwl_window)
|
||||
{
|
||||
|
@ -333,12 +370,53 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window)
|
|||
screen->DestroyPixmap(window_pixmap);
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
static Bool
|
||||
xwl_window_buffers_set_syncpts(struct xwl_window_buffer *xwl_window_buffer)
|
||||
{
|
||||
struct xwl_window *xwl_window = xwl_window_buffer->xwl_window;
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
uint64_t acquire_point = ++xwl_window_buffer->timeline_point;
|
||||
uint64_t release_point = ++xwl_window_buffer->timeline_point;
|
||||
|
||||
if (!xwl_window_buffer->syncobj) {
|
||||
struct dri3_syncobj *syncobj = xwl_glamor_dri3_syncobj_create(xwl_screen);
|
||||
if (!syncobj)
|
||||
goto fail;
|
||||
xwl_window_buffer->syncobj = syncobj;
|
||||
}
|
||||
|
||||
int fence_fd = xwl_glamor_get_fence(xwl_screen);
|
||||
if (fence_fd >= 0)
|
||||
xwl_window_buffer->syncobj->import_fence(xwl_window_buffer->syncobj,
|
||||
acquire_point, fence_fd);
|
||||
else
|
||||
goto fail;
|
||||
|
||||
xwl_glamor_dri3_syncobj_passthrough(xwl_window->window,
|
||||
xwl_window_buffer->syncobj,
|
||||
xwl_window_buffer->syncobj,
|
||||
acquire_point,
|
||||
release_point);
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
/* can't use explicit sync, we will do a glFinish() before presenting */
|
||||
if (xwl_window_buffer->syncobj) {
|
||||
xwl_window_buffer->syncobj->free(xwl_window_buffer->syncobj);
|
||||
xwl_window_buffer->syncobj = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
PixmapPtr
|
||||
xwl_window_swap_pixmap(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
struct xwl_window_buffer *xwl_window_buffer;
|
||||
PixmapPtr window_pixmap;
|
||||
Bool implicit_sync = TRUE;
|
||||
|
||||
window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
|
||||
|
||||
|
@ -350,6 +428,16 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
|
|||
BoxPtr pBox = RegionRects(full_damage);
|
||||
int nBox = RegionNumRects(full_damage);
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_window_buffer->syncobj) {
|
||||
int fence_fd =
|
||||
xwl_window_buffer->syncobj->export_fence(xwl_window_buffer->syncobj,
|
||||
xwl_window_buffer->timeline_point);
|
||||
xwl_glamor_wait_fence(xwl_screen, fence_fd);
|
||||
close(fence_fd);
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
while (nBox--) {
|
||||
copy_pixmap_area(window_pixmap,
|
||||
xwl_window_buffer->pixmap,
|
||||
|
@ -390,13 +478,35 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window)
|
|||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (!xwl_glamor_supports_implicit_sync(xwl_screen)) {
|
||||
if (xwl_screen->explicit_sync && xwl_window_buffers_set_syncpts(xwl_window_buffer)) {
|
||||
implicit_sync = FALSE;
|
||||
/* wait until the release fence is available before re-using this buffer */
|
||||
xwl_window_buffer->efd = eventfd(0, EFD_CLOEXEC);
|
||||
SetNotifyFd(xwl_window_buffer->efd, xwl_window_buffers_release_fence_avail,
|
||||
X_NOTIFY_READ, xwl_window_buffer);
|
||||
xwl_window_buffer->syncobj->submitted_eventfd(xwl_window_buffer->syncobj,
|
||||
xwl_window_buffer->timeline_point,
|
||||
xwl_window_buffer->efd);
|
||||
} else
|
||||
/* If glamor does not support implicit sync and we can't use
|
||||
* explicit sync, wait for the GPU to be idle before presenting.
|
||||
* Note that buffer re-use will still be unsynchronized :(
|
||||
*/
|
||||
glamor_finish(xwl_screen->screen);
|
||||
}
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
if (implicit_sync) {
|
||||
xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap,
|
||||
xwl_window_buffer_release_callback,
|
||||
xwl_window_buffer);
|
||||
|
||||
if (xwl_window->surface_sync) {
|
||||
wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync);
|
||||
xwl_window->surface_sync = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
xorg_list_append(&xwl_window_buffer->link_buffer,
|
||||
&xwl_window->window_buffers_unavailable);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "xdg-shell-client-protocol.h"
|
||||
#include "xwayland-shell-v1-client-protocol.h"
|
||||
#include "fractional-scale-v1-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
|
||||
#define DELAYED_WL_SURFACE_DESTROY 1000 /* ms */
|
||||
|
||||
|
@ -1496,6 +1497,9 @@ xwl_unrealize_window(WindowPtr window)
|
|||
if (xwl_window->fractional_scale)
|
||||
wp_fractional_scale_v1_destroy(xwl_window->fractional_scale);
|
||||
|
||||
if (xwl_window->surface_sync)
|
||||
wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync);
|
||||
|
||||
release_wl_surface_for_window(xwl_window);
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
xorg_list_del(&xwl_window->link_window);
|
||||
|
|
|
@ -84,6 +84,7 @@ struct xwl_window {
|
|||
struct wp_tearing_control_v1 *tearing_control;
|
||||
struct wp_fractional_scale_v1 *fractional_scale;
|
||||
int fractional_scale_numerator;
|
||||
struct wp_linux_drm_syncobj_surface_v1 *surface_sync;
|
||||
};
|
||||
|
||||
struct xwl_window *xwl_window_get(WindowPtr window);
|
||||
|
|
|
@ -64,7 +64,7 @@ libdrm_req = '>= 2.4.116'
|
|||
libselinux_req = '>= 2.0.86'
|
||||
xext_req = '>= 1.0.99.4'
|
||||
wayland_req = '>= 1.21.0'
|
||||
wayland_protocols_req = '>= 1.31'
|
||||
wayland_protocols_req = '>= 1.34'
|
||||
gbm_req = '>= 10.2'
|
||||
xf86dgaproto_req = '>= 2.0.99.1'
|
||||
xshmfence_req = '>= 1.1'
|
||||
|
|
|
@ -79,7 +79,10 @@ present_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc)
|
|||
}
|
||||
|
||||
#ifdef DRI3
|
||||
if (vblank->acquire_syncobj &&
|
||||
/* Defer execution of explicitly synchronized copies.
|
||||
* Flip synchronization is managed by the driver.
|
||||
*/
|
||||
if (!vblank->flip && vblank->acquire_syncobj &&
|
||||
!vblank->acquire_syncobj->is_signaled(vblank->acquire_syncobj,
|
||||
vblank->acquire_point)) {
|
||||
vblank->efd = eventfd(0, EFD_CLOEXEC);
|
||||
|
|
Loading…
Reference in New Issue