summaryrefslogtreecommitdiff
path: root/glamor/glamor_egl.c
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2013-12-31 00:07:42 -0800
committerEric Anholt <eric@anholt.net>2014-03-05 13:10:24 -0800
commitda08316605b26830b4d8f8fb2d9e69471cdc80ab (patch)
tree30011858644e18979e0d806cedf5edd5238d1cac /glamor/glamor_egl.c
parentfb4a1e6ef6f80a7670e92cab2bc490d4afd80a9b (diff)
glamor: Add support for DRI3.
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. v3: Don't put quite so much under GLAMOR_NO_DRI3, and add a comment explaining what this is about. Signed-off-by: Eric Anholt <eric@anholt.net> Reviewed-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'glamor/glamor_egl.c')
-rw-r--r--glamor/glamor_egl.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 56d89138e..05e6bd02e 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,30 @@ 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) {
+ /* Tell the core that we have the interfaces for import/export
+ * of pixmaps.
+ */
+ glamor_enable_dri3(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
+ * to stay out of the way and let it init DRI3 on its own.
+ */
+ if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) {
+ /* 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 +741,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);