Allow the modesetting present implementation to wait on in-fences using ANDROID_native_fence_sync if the fence was created with DRI3 FenceFromDMAFenceFD.
Signed-off-by: Louis-Francis Ratté-Boulianne <l...@collabora.com> --- configure.ac | 1 + glamor/Makefile.am | 2 + glamor/glamor.c | 19 ++++++ glamor/glamor.h | 7 +++ glamor/glamor_egl.c | 44 ++++++++++++++ glamor/glamor_egl_stubs.c | 6 ++ hw/xfree86/drivers/modesetting/dri2.c | 2 +- hw/xfree86/drivers/modesetting/driver.h | 1 + hw/xfree86/drivers/modesetting/drmmode_display.c | 7 ++- hw/xfree86/drivers/modesetting/drmmode_display.h | 2 +- hw/xfree86/drivers/modesetting/pageflip.c | 14 +++-- hw/xfree86/drivers/modesetting/present.c | 77 +++++++++++++++++++++++- hw/xwayland/xwayland-glamor.c | 12 ++++ 13 files changed, 184 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 5f75b5d07..eb8cc8e07 100644 --- a/configure.ac +++ b/configure.ac @@ -1537,6 +1537,7 @@ MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' MIEXT_SYNC_INC='-I$(top_srcdir)/miext/sync' MIEXT_SYNC_LIB='$(top_builddir)/miext/sync/libsync.la' CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' +AC_SUBST([MIEXT_SYNC_LIB]) # SHA1 hashing AC_ARG_WITH([sha1], diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 8c79994e0..29b488d22 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -2,6 +2,8 @@ noinst_LTLIBRARIES = libglamor.la libglamor_egl_stubs.la libglamor_la_LIBADD = $(GLAMOR_LIBS) +libglamor_la_DEPENDENCIES = $(MIEXT_SYNC_LIB) + AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS) libglamor_la_SOURCES = \ diff --git a/glamor/glamor.c b/glamor/glamor.c index 35b3cbeed..96eb8b18a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -260,6 +260,25 @@ _glamor_block_handler(ScreenPtr screen, void *timeout) screen->BlockHandler = _glamor_block_handler; } +Bool +glamor_support_fence(ScreenPtr screen, SyncFence *fence) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) + return glamor_egl_support_fence(screen, fence); + return FALSE; +} + +void +glamor_add_fence(ScreenPtr screen, SyncFence *fence) +{ + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + + if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN) + glamor_egl_add_fence(screen, fence); +} + static void glamor_set_debug_level(int *debug_level) { diff --git a/glamor/glamor.h b/glamor/glamor.h index 600ccf98b..32f342339 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -35,6 +35,7 @@ #include <picturestr.h> #include <fb.h> #include <fbpict.h> +#include <misync.h> #ifdef GLAMOR_FOR_XORG #include <xf86xv.h> #endif @@ -117,6 +118,9 @@ extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type); extern _X_EXPORT void glamor_block_handler(ScreenPtr screen); +extern _X_EXPORT Bool glamor_support_fence(ScreenPtr screen, SyncFence *fence); +extern _X_EXPORT void glamor_add_fence(ScreenPtr screen, SyncFence *fence); + extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage); extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap); @@ -127,6 +131,9 @@ extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap); #define GLAMOR_CREATE_NO_LARGE 0x105 #define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106 +extern _X_EXPORT Bool glamor_egl_support_fence(ScreenPtr screen, SyncFence *fence); +extern _X_EXPORT Bool glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence); + /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo). * * @front: front pixmap. diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 5ee972708..e57c8cb43 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -46,6 +46,7 @@ #include "glamor.h" #include "glamor_priv.h" #include "dri3.h" +#include "misync.h" struct glamor_egl_screen_private { EGLDisplay display; @@ -93,6 +94,49 @@ glamor_egl_make_current(struct glamor_context *glamor_ctx) } } +Bool +glamor_egl_support_fence(ScreenPtr pScreen, + SyncFence *fence) +{ + struct glamor_egl_screen_private *glamor_egl; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(pScreen)); + return (glamor_egl->dmafence_capable && fence != NULL && + miSyncGetFenceType(fence) == SYNC_FENCE_DMA); +} + +Bool +glamor_egl_add_fence(ScreenPtr pScreen, + SyncFence *fence) +{ + struct glamor_egl_screen_private *glamor_egl; + EGLSyncKHR sync; + EGLint attribs[3]; + int i = 0; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(pScreen)); + if (!glamor_egl->dmafence_capable || fence == NULL) + return FALSE; + + attribs[i++] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; + attribs[i++] = miSyncTakeDMAFenceFDFromFence(pScreen, fence); + attribs[i++] = EGL_NONE; + + if (!eglMakeCurrent(glamor_egl->display, + EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) + return FALSE; + + sync = eglCreateSyncKHR(glamor_egl->display, EGL_SYNC_NATIVE_FENCE_ANDROID, + attribs); + if (sync == EGL_NO_SYNC_KHR) + return FALSE; + + eglWaitSyncKHR(glamor_egl->display, sync, 0); + eglDestroySyncKHR(glamor_egl->display, sync); + + return TRUE; +} + static int glamor_get_flink_name(int fd, int handle, int *name) { diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c index aae909e9f..e5261e640 100644 --- a/glamor/glamor_egl_stubs.c +++ b/glamor/glamor_egl_stubs.c @@ -51,3 +51,9 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, { return 0; } + +Bool +glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence) +{ + return FALSE; +} diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c index f60d337de..d084858b0 100644 --- a/hw/xfree86/drivers/modesetting/dri2.c +++ b/hw/xfree86/drivers/modesetting/dri2.c @@ -494,7 +494,7 @@ ms_dri2_schedule_flip(ms_dri2_frame_event_ptr info) event->event_data = info->event_data; if (ms_do_pageflip(screen, back_priv->pixmap, event, - drmmode_crtc->vblank_pipe, FALSE, + drmmode_crtc->vblank_pipe, FALSE, NULL, ms_dri2_flip_handler, ms_dri2_flip_abort)) { ms->drmmode.dri2_flipping = TRUE; diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 74603864f..4ae69c7b4 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -155,6 +155,7 @@ Bool ms_do_pageflip(ScreenPtr screen, void *event, int ref_crtc_vblank_pipe, Bool async, + SyncFence *in_fence, ms_pageflip_handler_proc pageflip_handler, ms_pageflip_abort_proc pageflip_abort); diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index 8db516754..ec3a8f121 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -458,7 +458,7 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn, int drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id, - int x, int y, uint32_t flags, void *data) + int x, int y, int in_fence_fd, uint32_t flags, void *data) { modesettingPtr ms = modesettingPTR(crtc->scrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); @@ -529,6 +529,9 @@ drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id, drmmode->front_bo.width); ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_CRTC_H, drmmode->front_bo.height); + if (in_fence_fd > -1) + ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_IN_FENCE_FD, + in_fence_fd); if (ret == 0) ret = drmModeAtomicCommit(ms->fd, req, flags, data); @@ -1194,7 +1197,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - if (drmmode_crtc_set_fb(crtc, mode, fb_id, x, y, flags, NULL)) { + if (drmmode_crtc_set_fb(crtc, mode, fb_id, x, y, -1, flags, NULL)) { xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "failed to set mode: %s\n", strerror(errno)); ret = FALSE; diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index 8a6698e0d..14fb35c37 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -277,7 +277,7 @@ void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmmode, void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode); int drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id, - int x, int y, uint32_t flags, void *data); + int x, int y, int fence_fd, uint32_t flags, void *data); Bool drmmode_support_dma_fences(ScrnInfoPtr pScrn); diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c index 2aba9f2f5..c376ffad8 100644 --- a/hw/xfree86/drivers/modesetting/pageflip.c +++ b/hw/xfree86/drivers/modesetting/pageflip.c @@ -24,6 +24,7 @@ #include "dix-config.h" #endif +#include <unistd.h> #include <xserver_poll.h> #include <xf86drm.h> @@ -75,6 +76,7 @@ ms_flush_drm_events(ScreenPtr screen) struct ms_flipdata { ScreenPtr screen; void *event; + int in_fence_fd; ms_pageflip_handler_proc event_handler; ms_pageflip_abort_proc abort_handler; /* number of CRTC events referencing this */ @@ -108,6 +110,8 @@ ms_pageflip_free(struct ms_crtc_pageflip *flip) free(flip); if (--flipdata->flip_count > 0) return; + if (flipdata->in_fence_fd != -1) + close(flipdata->in_fence_fd); free(flipdata); } @@ -161,15 +165,15 @@ ms_pageflip_abort(void *data) static Bool do_queue_flip_on_crtc(modesettingPtr ms, xf86CrtcPtr crtc, - uint32_t flags, uint32_t seq) + int fence_fd, uint32_t flags, uint32_t seq) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; #ifdef GLAMOR_HAS_DRM_ATOMIC if (ms->atomic_modeset) { flags |= DRM_MODE_ATOMIC_NONBLOCK; - return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0, flags, - (void *) (uintptr_t) seq); + return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0, fence_fd, + flags, (void *) (uintptr_t) seq); } #endif @@ -212,7 +216,7 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc, /* take a reference on flipdata for use in flip */ flipdata->flip_count++; - while (do_queue_flip_on_crtc(ms, crtc, flags, seq)) { + while (do_queue_flip_on_crtc(ms, crtc, flipdata->in_fence_fd, flags, seq)) { err = errno; /* We may have failed because the event queue was full. Flush it * and retry. If there was nothing to flush, then we failed for @@ -241,6 +245,7 @@ ms_do_pageflip(ScreenPtr screen, void *event, int ref_crtc_vblank_pipe, Bool async, + SyncFence *in_fence, ms_pageflip_handler_proc pageflip_handler, ms_pageflip_abort_proc pageflip_abort) { @@ -275,6 +280,7 @@ ms_do_pageflip(ScreenPtr screen, flipdata->event = event; flipdata->screen = screen; + flipdata->in_fence_fd = in_fence ? dup(miSyncDMAFenceFDFromFence(screen, in_fence)) : -1; flipdata->event_handler = pageflip_handler; flipdata->abort_handler = pageflip_abort; diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c index af995adac..fa53cb10b 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -313,7 +313,47 @@ ms_present_flip(RRCrtcPtr crtc, event->unflip = FALSE; ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip, - ms_present_flip_handler, ms_present_flip_abort); + NULL, ms_present_flip_handler, ms_present_flip_abort); + if (!ret) + xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); + else + ms->drmmode.present_flipping = TRUE; + + return ret; +} + +static Bool +ms_present_flip_with_fence(RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + SyncFence *flip_fence, + SyncFence *idle_fence, + Bool sync_flip) +{ + ScreenPtr screen = crtc->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + xf86CrtcPtr xf86_crtc = crtc->devPrivate; + drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + Bool ret; + struct ms_present_vblank_event *event; + + if (!ms_present_check_flip(crtc, screen->root, pixmap, sync_flip)) + return FALSE; + + event = calloc(1, sizeof(struct ms_present_vblank_event)); + if (!event) + return FALSE; + + DebugPresent(("\t\tms:pf %lld msc %llu\n", + (long long) event_id, (long long) target_msc)); + + event->event_id = event_id; + event->unflip = FALSE; + + ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip, + flip_fence, ms_present_flip_handler, ms_present_flip_abort); if (!ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); else @@ -343,7 +383,7 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id) event->unflip = TRUE; if (ms_present_check_flip(NULL, screen->root, pixmap, TRUE) && - ms_do_pageflip(screen, pixmap, event, -1, FALSE, + ms_do_pageflip(screen, pixmap, event, -1, FALSE, NULL, ms_present_flip_handler, ms_present_flip_abort)) { return; } @@ -374,6 +414,36 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id) present_event_notify(event_id, 0, 0); ms->drmmode.present_flipping = FALSE; } + +static Bool +ms_present_can_wait_fence(RRCrtcPtr crtc, + SyncFence *fence) +{ +#ifdef GLAMOR_HAS_DRM_ATOMIC + if (crtc) { + ScreenPtr screen = crtc->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + + return (fence && miSyncGetFenceType(fence) == SYNC_FENCE_DMA && + drmmode_support_dma_fences(scrn) && + glamor_support_fence(screen, fence) && + ms->atomic_modeset); + } +#endif + return FALSE; +} + +/* Add a fence in the command stream + */ +static void +ms_present_wait_fence(RRCrtcPtr crtc, + SyncFence *fence) +{ + if (crtc) + glamor_add_fence(crtc->pScreen, fence); +} + #endif static present_screen_info_rec ms_present_screen_info = { @@ -389,7 +459,10 @@ static present_screen_info_rec ms_present_screen_info = { #ifdef GLAMOR_HAS_GBM .check_flip = ms_present_check_flip, .flip = ms_present_flip, + .flip_with_fence = ms_present_flip_with_fence, .unflip = ms_present_unflip, + .can_wait_fence = ms_present_can_wait_fence, + .wait_fence = ms_present_wait_fence, #endif }; diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index 40772fb9a..44218a1c8 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -537,6 +537,18 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen, return 0; } +Bool +glamor_egl_support_fence(ScreenPtr screen, SyncFence *fence) +{ + return FALSE; +} + +Bool +glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence) +{ + return FALSE; +} + struct xwl_auth_state { int fd; ClientPtr client; -- 2.13.0 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel