[PATCH 6/6] glamor: Add support for DRI3.

Eric Anholt eric at anholt.net
Mon Feb 24 17:47:43 PST 2014


The render-nodes case is untested.

v2: Add a flag for wayland to suppress the native DRI3 support.
    Wayland isn't running as a master itself, so it can't do the auth
    on its own and has to ask the compositor to do it for us.  Dropped
    XXX about randr provider -- the conclusion from discussion with
    keithp was that if the driver's dri3_open for a provider on a
    different screen, that's a core dri3 bug.

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/glamor.h                   |  4 +-
 glamor/glamor_egl.c               | 78 +++++++++++++++++++++++++++++++++++++++
 hw/xfree86/glamor_egl/Makefile.am |  5 ++-
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 20988f4..d3520ab 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -67,10 +67,12 @@ typedef enum glamor_pixmap_type {
 #define GLAMOR_USE_SCREEN		(1 << 1)
 #define GLAMOR_USE_PICTURE_SCREEN 	(1 << 2)
 #define GLAMOR_USE_EGL_SCREEN		(1 << 3)
+#define GLAMOR_NO_DRI3			(1 << 4)
 #define GLAMOR_VALID_FLAGS      (GLAMOR_INVERTED_Y_AXIS  		\
 				 | GLAMOR_USE_SCREEN 			\
                                  | GLAMOR_USE_PICTURE_SCREEN		\
-				 | GLAMOR_USE_EGL_SCREEN)
+				 | GLAMOR_USE_EGL_SCREEN                \
+                                 | GLAMOR_NO_DRI3)
 
 /* @glamor_init: Initialize glamor internal data structure.
  *
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 56d8913..c883777 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -50,6 +50,7 @@
 
 #include "glamor.h"
 #include "glamor_priv.h"
+#include "dri3.h"
 
 static const char glamor_name[] = "glamor";
 
@@ -68,6 +69,7 @@ struct glamor_egl_screen_private {
     EGLDisplay display;
     EGLContext context;
     EGLint major, minor;
+    char *device_path;
 
     CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr CloseScreen;
@@ -627,10 +629,67 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl,
     return FALSE;
 }
 
+static int
+glamor_dri3_open(ScreenPtr screen,
+                 RRProviderPtr provider,
+                 int *fdp)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_egl_screen_private *glamor_egl =
+        glamor_egl_get_screen_private(scrn);
+    int fd;
+    drm_magic_t magic;
+
+    fd = open(glamor_egl->device_path, O_RDWR|O_CLOEXEC);
+    if (fd < 0)
+        return BadAlloc;
+
+    /* Before FD passing in the X protocol with DRI3 (and increased
+     * security of rendering with per-process address spaces on the
+     * GPU), the kernel had to come up with a way to have the server
+     * decide which clients got to access the GPU, which was done by
+     * each client getting a unique (magic) number from the kernel,
+     * passing it to the server, and the server then telling the
+     * kernel which clients were authenticated for using the device.
+     *
+     * Now that we have FD passing, the server can just set up the
+     * authentication on its own and hand the prepared FD off to the
+     * client.
+     */
+    if (drmGetMagic(fd, &magic) < 0) {
+        if (errno == EACCES) {
+            /* Assume that we're on a render node, and the fd is
+             * already as authenticated as it should be.
+             */
+            *fdp = fd;
+            return Success;
+        } else {
+            close(fd);
+            return BadMatch;
+        }
+    }
+
+    if (drmAuthMagic(glamor_egl->fd, magic) < 0) {
+        close(fd);
+        return BadMatch;
+    }
+
+    *fdp = fd;
+    return Success;
+}
+
+static dri3_screen_info_rec glamor_dri3_info = {
+    .version = 0,
+    .open = glamor_dri3_open,
+    .pixmap_from_fd = glamor_pixmap_from_fd,
+    .fd_from_pixmap = glamor_fd_from_pixmap,
+};
+
 void
 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
 
@@ -642,6 +701,23 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 
     glamor_ctx->get_context = glamor_egl_get_context;
     glamor_ctx->put_context = glamor_egl_put_context;
+
+    if (glamor_egl->dri3_capable && !(glamor_priv->flags & GLAMOR_NO_DRI3)) {
+        /* Tell the core that we have the interfaces for import/export
+         * of pixmaps.
+         */
+        glamor_enable_dri3(screen);
+
+        /* To do DRI3 device FD generation, we need to open a new fd
+         * to the same device we were handed in originally.
+         */
+        glamor_egl->device_path = drmGetDeviceNameFromFd(glamor_egl->fd);
+
+        if (!dri3_screen_init(screen, &glamor_dri3_info)) {
+            xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                       "Failed to initialize DRI3.\n");
+        }
+    }
 }
 
 static void
@@ -658,6 +734,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn)
         if (glamor_egl->gbm)
             gbm_device_destroy(glamor_egl->gbm);
 #endif
+        free(glamor_egl->device_path);
+
         scrn->FreeScreen = glamor_egl->saved_free_screen;
         free(glamor_egl);
         scrn->FreeScreen(scrn);
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
index bb1b511..85e1c0c 100644
--- a/hw/xfree86/glamor_egl/Makefile.am
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -36,5 +36,8 @@ libglamoregl_la_LIBADD = \
 	$(top_builddir)/glamor/libglamor.la \
 	$()
 
-AM_CPPFLAGS = $(XORG_INCS)
+AM_CPPFLAGS = $(XORG_INCS) \
+	-I$(top_srcdir)/dri3 \
+	$()
+
 AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
-- 
1.9.rc1



More information about the xorg-devel mailing list