Create out-fence using eglCreateSyncKHR or OUT_FENCE_PTR DRM property when page-flipping.
Signed-off-by: Louis-Francis Ratté-Boulianne <l...@collabora.com> --- glamor/glamor.c | 9 ++++++ glamor/glamor.h | 2 ++ glamor/glamor_egl.c | 37 ++++++++++++++++++++++++ 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 | 10 +++++-- hw/xfree86/drivers/modesetting/drmmode_display.h | 3 +- hw/xfree86/drivers/modesetting/pageflip.c | 22 ++++++++++++-- hw/xfree86/drivers/modesetting/present.c | 23 +++++++++++++-- hw/xwayland/xwayland-glamor.c | 6 ++++ 11 files changed, 111 insertions(+), 10 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 96eb8b18a..4be481a2a 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -279,6 +279,15 @@ glamor_add_fence(ScreenPtr screen, SyncFence *fence) glamor_egl_add_fence(screen, fence); } +void +glamor_create_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_create_fence(screen, fence); +} + static void glamor_set_debug_level(int *debug_level) { diff --git a/glamor/glamor.h b/glamor/glamor.h index 32f342339..f0265049e 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -120,6 +120,7 @@ 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 void glamor_create_fence(ScreenPtr screen, SyncFence *fence); extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, unsigned int usage); @@ -133,6 +134,7 @@ extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap); extern _X_EXPORT Bool glamor_egl_support_fence(ScreenPtr screen, SyncFence *fence); extern _X_EXPORT Bool glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence); +extern _X_EXPORT Bool glamor_egl_create_fence(ScreenPtr screen, SyncFence *fence); /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo). * diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index e57c8cb43..94dc7790a 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -137,6 +137,43 @@ glamor_egl_add_fence(ScreenPtr pScreen, return TRUE; } +Bool +glamor_egl_create_fence(ScreenPtr pScreen, + SyncFence *fence) +{ + struct glamor_egl_screen_private *glamor_egl; + EGLSyncKHR sync; + EGLint attribs[3]; + int i = 0; + int fd; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(pScreen)); + if (!glamor_egl->dmafence_capable) + return FALSE; + + attribs[i++] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; + attribs[i++] = EGL_NO_NATIVE_FENCE_FD_ANDROID; + 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; + + glFlush(); + + fd = eglDupNativeFenceFDANDROID(glamor_egl->display, sync); + miSyncInitFenceFromDMAFenceFD(pScreen, fence, fd); + close(fd); + 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 e5261e640..9eb2514c2 100644 --- a/glamor/glamor_egl_stubs.c +++ b/glamor/glamor_egl_stubs.c @@ -57,3 +57,9 @@ glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence) { return FALSE; } + +Bool +glamor_egl_create_fence(ScreenPtr screen, SyncFence *fence) +{ + return FALSE; +} diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c index d084858b0..b4bba6260 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, NULL, + drmmode_crtc->vblank_pipe, FALSE, NULL, 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 4ae69c7b4..505a78071 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -156,6 +156,7 @@ Bool ms_do_pageflip(ScreenPtr screen, int ref_crtc_vblank_pipe, Bool async, SyncFence *in_fence, + SyncFence *out_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 ec3a8f121..e8e7dff39 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -52,6 +52,8 @@ #include "driver.h" +#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) + static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height); static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height, int depth, int bitsPerPixel, int devKind, @@ -458,7 +460,8 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn, int drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id, - int x, int y, int in_fence_fd, uint32_t flags, void *data) + int x, int y, int in_fence_fd, int *out_fence_ptr, + uint32_t flags, void *data) { modesettingPtr ms = modesettingPTR(crtc->scrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); @@ -532,6 +535,9 @@ drmmode_crtc_set_fb(xf86CrtcPtr crtc, DisplayModePtr mode, uint32_t fb_id, if (in_fence_fd > -1) ret |= plane_add_prop(req, drmmode_crtc, DRMMODE_PLANE_IN_FENCE_FD, in_fence_fd); + if (out_fence_ptr) + ret |= crtc_add_prop(req, drmmode_crtc, DRMMODE_CRTC_OUT_FENCE_PTR, + VOID2U64(out_fence_ptr)); if (ret == 0) ret = drmModeAtomicCommit(ms->fd, req, flags, data); @@ -1197,7 +1203,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, -1, flags, NULL)) { + if (drmmode_crtc_set_fb(crtc, mode, fb_id, x, y, -1, NULL, 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 14fb35c37..8acc3398d 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -277,7 +277,8 @@ 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, int fence_fd, uint32_t flags, void *data); + int x, int y, int in_fence_fd, int *out_fence_ptr, + 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 c376ffad8..2fa713718 100644 --- a/hw/xfree86/drivers/modesetting/pageflip.c +++ b/hw/xfree86/drivers/modesetting/pageflip.c @@ -77,6 +77,7 @@ struct ms_flipdata { ScreenPtr screen; void *event; int in_fence_fd; + SyncFence *out_fence; ms_pageflip_handler_proc event_handler; ms_pageflip_abort_proc abort_handler; /* number of CRTC events referencing this */ @@ -165,14 +166,16 @@ ms_pageflip_abort(void *data) static Bool do_queue_flip_on_crtc(modesettingPtr ms, xf86CrtcPtr crtc, - int fence_fd, uint32_t flags, uint32_t seq) + int in_fence_fd, int *out_fence_ptr, + 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, fence_fd, + return drmmode_crtc_set_fb(crtc, NULL, ms->drmmode.fb_id, 0, 0, + in_fence_fd, out_fence_ptr, flags, (void *) (uintptr_t) seq); } #endif @@ -193,6 +196,8 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc, struct ms_crtc_pageflip *flip; uint32_t seq; int err; + int out_fence_fd = -1; + int *out_fence_ptr = NULL; flip = calloc(1, sizeof(struct ms_crtc_pageflip)); if (flip == NULL) { @@ -216,7 +221,10 @@ 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, flipdata->in_fence_fd, flags, seq)) { + if (flipdata->out_fence) + out_fence_ptr = &out_fence_fd; + + while (do_queue_flip_on_crtc(ms, crtc, flipdata->in_fence_fd, out_fence_ptr, 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 @@ -234,6 +242,12 @@ queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc, xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n"); } + if (flipdata->out_fence) { + miSyncInitFenceFromDMAFenceFD(screen, flipdata->out_fence, out_fence_fd); + if (out_fence_fd > -1) + close(out_fence_fd); + } + /* The page flip succeded. */ return TRUE; } @@ -246,6 +260,7 @@ ms_do_pageflip(ScreenPtr screen, int ref_crtc_vblank_pipe, Bool async, SyncFence *in_fence, + SyncFence *out_fence, ms_pageflip_handler_proc pageflip_handler, ms_pageflip_abort_proc pageflip_abort) { @@ -281,6 +296,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->out_fence = out_fence; 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 fa53cb10b..61f42c42b 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -313,7 +313,7 @@ ms_present_flip(RRCrtcPtr crtc, event->unflip = FALSE; ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip, - NULL, ms_present_flip_handler, ms_present_flip_abort); + NULL, NULL, ms_present_flip_handler, ms_present_flip_abort); if (!ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); else @@ -353,7 +353,8 @@ ms_present_flip_with_fence(RRCrtcPtr crtc, 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); + flip_fence, idle_fence, + ms_present_flip_handler, ms_present_flip_abort); if (!ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); else @@ -363,6 +364,21 @@ ms_present_flip_with_fence(RRCrtcPtr crtc, } /* + * Flush our batch buffer when requested by the Present extension. + */ +static void +ms_present_flush_with_fence(WindowPtr window, + SyncFence *idle_fence) +{ + ScreenPtr screen = window->drawable.pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); + + if (ms->drmmode.glamor) + glamor_create_fence(screen, idle_fence); +} + +/* * Queue a flip back to the normal frame buffer */ static void @@ -383,7 +399,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, NULL, + ms_do_pageflip(screen, pixmap, event, -1, FALSE, NULL, NULL, ms_present_flip_handler, ms_present_flip_abort)) { return; } @@ -460,6 +476,7 @@ static present_screen_info_rec ms_present_screen_info = { .check_flip = ms_present_check_flip, .flip = ms_present_flip, .flip_with_fence = ms_present_flip_with_fence, + .flush_with_fence = ms_present_flush_with_fence, .unflip = ms_present_unflip, .can_wait_fence = ms_present_can_wait_fence, .wait_fence = ms_present_wait_fence, diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index 44218a1c8..1ce7b982e 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -549,6 +549,12 @@ glamor_egl_add_fence(ScreenPtr screen, SyncFence *fence) return FALSE; } +Bool +glamor_egl_create_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