[RFC v2 12/12] modesetting: Add implementation for out-fences
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Wed Sep 27 05:20:03 UTC 2017
Create out-fence using eglCreateSyncKHR or OUT_FENCE_PTR DRM
property when page-flipping.
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at 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
More information about the xorg-devel
mailing list