[RFC xserver v3 10/11] modesetting: Add implementation for in-fences
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Mon Nov 6 21:42:59 UTC 2017
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 <lfrb at 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 | 12 ++++
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, 190 insertions(+), 10 deletions(-)
diff --git a/configure.ac b/configure.ac
index 81d18b2e7..7fbb57f02 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 af0481dc8..673b7b2d4 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 e2437ee77..7f19373ff 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 &&
+ miSyncIsDMAFence(fence));
+}
+
+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..755f85959 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -51,3 +51,15 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
{
return 0;
}
+
+Bool
+glamor_egl_support_fence(ScreenPtr screen, SyncFence *fence)
+{
+ return FALSE;
+}
+
+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 b2278e78b..f249537d4 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 2014002bd..c5e79b684 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -172,6 +172,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 dca042faa..6092a3878 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -498,7 +498,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);
@@ -569,6 +569,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);
@@ -1230,7 +1233,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 23ca43bd3..55471c80d 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -279,7 +279,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 26738f928..75b3ae4ab 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 48fe8909c..b620a6009 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -324,7 +324,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
@@ -354,7 +394,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;
}
@@ -385,6 +425,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 && miSyncIsDMAFence(fence) &&
+ 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 = {
@@ -401,7 +471,10 @@ static present_screen_info_rec ms_present_screen_info = {
.check_flip = ms_present_check_flip,
.check_flip2 = ms_present_check_flip2,
.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
More information about the xorg-devel
mailing list