[RFC xserver 09/12] modesetting: Check if DMA fences are supported

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Wed Aug 30 05:16:58 UTC 2017


Modesetting/glamor can handle DMA fences if extensions EGL_KHR_wait_sync and
EGL_ANDROID_native_fence_sync are available and if IN_FENCE_FD
and OUT_FENCE_PTR DRM properties are implemented.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 glamor/glamor.c                                  | 16 ++++++++++++++
 glamor/glamor.h                                  | 16 ++++++++++++++
 glamor/glamor_egl.c                              | 10 +++++++++
 glamor/glamor_egl_ext.h                          | 28 ++++++++++++++++++++++++
 glamor/glamor_priv.h                             |  1 +
 hw/xfree86/drivers/modesetting/drmmode_display.c | 23 +++++++++++++++++++
 hw/xfree86/drivers/modesetting/drmmode_display.h |  4 ++++
 hw/xfree86/drivers/modesetting/present.c         |  3 +++
 8 files changed, 101 insertions(+)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index f0113534e..8b6b3f7de 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -804,6 +804,22 @@ glamor_supports_pixmap_import_export(ScreenPtr screen)
     return glamor_priv->dri3_enabled;
 }
 
+void
+glamor_enable_dma_fences(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_priv->dma_fences_enabled = TRUE;
+}
+
+Bool
+glamor_supports_dma_fences(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    return glamor_priv->dma_fences_enabled;
+}
+
 _X_EXPORT int
 glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
                        uint32_t *strides, uint32_t *offsets,
diff --git a/glamor/glamor.h b/glamor/glamor.h
index ddf67fe20..bfaf35f0d 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -138,6 +138,7 @@ extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front,
 
 /* The DDX is not supposed to call these three functions */
 extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen);
+extern _X_EXPORT void glamor_enable_dma_fences(ScreenPtr screen);
 extern _X_EXPORT int glamor_egl_fds_from_pixmap(ScreenPtr, PixmapPtr, int *,
                                                 uint32_t *, uint32_t *,
                                                 uint64_t *);
@@ -161,6 +162,21 @@ extern _X_EXPORT struct gbm_device *glamor_egl_get_gbm_device(ScreenPtr screen);
  * */
 extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen);
 
+/* @glamor_supports_dma_fences: Returns Glamor can wait on
+ * DMA in-fences and create DMA out-fences.
+ *
+ * @screen: Current screen pointer.
+ *
+ * To have DMA fences support enabled, glamor and glamor_egl need
+ * to be initialized.
+ *
+ * The EGL layer needs to have the following extensions working:
+ *
+ * .EGL_ANDROID_native_fence_sync
+ * .EGL_KHR_wait_sync
+ * */
+extern _X_EXPORT Bool glamor_supports_dma_fences(ScreenPtr screen);
+
 /* @glamor_fds_from_pixmap: Get a dma-buf fd from a pixmap.
  *
  * @screen: Current screen pointer.
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 5c7e5b790..cb4f05ddf 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -57,6 +57,7 @@ struct glamor_egl_screen_private {
     int fd;
     struct gbm_device *gbm;
     int dmabuf_capable;
+    int dmafence_capable;
 
     CloseScreenProcPtr saved_close_screen;
     DestroyPixmapProcPtr saved_destroy_pixmap;
@@ -745,6 +746,9 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
      */
     glamor_enable_dri3(screen);
 
+    if (glamor_egl->dmafence_capable)
+        glamor_enable_dma_fences(screen);
+
     /* If the driver wants to do its own auth dance (e.g. Xwayland
      * on pre-3.15 kernels that don't have render nodes and thus
      * has the wayland compositor as a master), then it needs us
@@ -920,6 +924,12 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
         glamor_egl->dmabuf_capable = TRUE;
 #endif
 
+    if (epoxy_has_egl_extension(glamor_egl->display,
+                                "EGL_ANDROID_native_fence_sync") &&
+        epoxy_has_egl_extension(glamor_egl->display,
+                                "EGL_KHR_wait_sync"))
+        glamor_egl->dmafence_capable = TRUE;
+
     glamor_egl->saved_free_screen = scrn->FreeScreen;
     scrn->FreeScreen = glamor_egl_free_screen;
     return TRUE;
diff --git a/glamor/glamor_egl_ext.h b/glamor/glamor_egl_ext.h
index 436e52137..a8d29f9e7 100644
--- a/glamor/glamor_egl_ext.h
+++ b/glamor/glamor_egl_ext.h
@@ -62,4 +62,32 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dp
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
 #endif
 
+/* Define tokens from EGL_KHR_fence_sync */
+#ifndef EGL_KHR_fence_sync
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR            0x30F8
+#define EGL_SYNC_FENCE_KHR                0x30F9
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
+
+/* Define tokens from EGL_KHR_wait_sync */
+#ifndef EGL_KHR_wait_sync
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#endif /* EGL_KHR_wait_sync */
+
+/* Define tokens from EGL_ANDROID_native_fence_sync */
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_SYNC_NATIVE_FENCE_ANDROID     0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID  0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID    -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#endif /* EGL_ANDROID_native_fence_sync */
+
 #endif /* GLAMOR_EGL_EXT_H */
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 07a98efeb..c57580067 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -285,6 +285,7 @@ typedef struct glamor_screen_private {
     int flags;
     ScreenPtr screen;
     int dri3_enabled;
+    int dma_fences_enabled;
 
     Bool suppress_gl_out_of_memory_logging;
     Bool logged_any_fbo_allocation_failure;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 31a665c7d..e39009a17 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -1705,6 +1705,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
         },
         [DRMMODE_PLANE_FB_ID] = { .name = "FB_ID", },
         [DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
+        [DRMMODE_PLANE_IN_FENCE_FD] = { .name = "IN_FENCE_FD", },
         [DRMMODE_PLANE_IN_FORMATS] = { .name = "IN_FORMATS", },
         [DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
         [DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
@@ -1814,6 +1815,27 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
 }
 #endif
 
+Bool
+drmmode_support_dma_fences(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+        xf86CrtcPtr crtc = xf86_config->crtc[i];
+        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+        if (!crtc->enabled)
+            continue;
+
+        if (drmmode_crtc->props_plane[DRMMODE_PLANE_IN_FENCE_FD].prop_id == 0 ||
+            drmmode_crtc->props[DRMMODE_CRTC_OUT_FENCE_PTR].prop_id == 0)
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
 static unsigned int
 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
 {
@@ -1825,6 +1847,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
     static const drmmode_prop_info_rec crtc_props[] = {
         [DRMMODE_CRTC_ACTIVE] = { .name = "ACTIVE" },
         [DRMMODE_CRTC_MODE_ID] = { .name = "MODE_ID" },
+        [DRMMODE_CRTC_OUT_FENCE_PTR] = { .name = "OUT_FENCE_PTR" },
     };
 #endif
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 28ffd772e..754cbedc2 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -39,6 +39,7 @@ struct gbm_device;
 enum drmmode_plane_property {
     DRMMODE_PLANE_TYPE = 0,
     DRMMODE_PLANE_FB_ID,
+    DRMMODE_PLANE_IN_FENCE_FD,
     DRMMODE_PLANE_IN_FORMATS,
     DRMMODE_PLANE_CRTC_ID,
     DRMMODE_PLANE_SRC_X,
@@ -64,6 +65,7 @@ enum drmmode_connector_property {
 enum drmmode_crtc_property {
     DRMMODE_CRTC_ACTIVE,
     DRMMODE_CRTC_MODE_ID,
+    DRMMODE_CRTC_OUT_FENCE_PTR,
     DRMMODE_CRTC__COUNT
 };
 
@@ -270,6 +272,8 @@ 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);
 
+Bool drmmode_support_dma_fences(ScrnInfoPtr pScrn);
+
 #ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
 #define DRM_CAP_DUMB_PREFERRED_DEPTH 3
 #endif
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index fcff8ee16..be2af71dc 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -404,5 +404,8 @@ ms_present_screen_init(ScreenPtr screen)
     if (ret == 0 && value == 1)
         ms_present_screen_info.capabilities |= PresentCapabilityAsync;
 
+    if (drmmode_support_dma_fences(scrn) && glamor_supports_dma_fences(screen))
+        ms_present_screen_info.capabilities |= PresentCapabilityIdleFence;
+
     return present_screen_init(screen, &ms_present_screen_info);
 }
-- 
2.13.0



More information about the xorg-devel mailing list