[PATCH 14/14] Add DRI3 support v2

Michel Dänzer michel at daenzer.net
Sun Mar 15 23:33:41 PDT 2015


From: Michel Dänzer <michel.daenzer at amd.com>

Must be enabled with

	Option	"DRI3"

in xorg.conf.

v2: Adapt to v2 of patches 11/12.
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 configure.ac      |   4 ++
 man/radeon.man    |   4 ++
 src/Makefile.am   |   5 +-
 src/radeon.h      |   4 ++
 src/radeon_dri3.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/radeon_kms.c  |  21 +++++-
 6 files changed, 236 insertions(+), 3 deletions(-)
 create mode 100644 src/radeon_dri3.c

diff --git a/configure.ac b/configure.ac
index 71d8ff0..acd9fe0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -143,6 +143,10 @@ AC_CHECK_HEADERS([present.h], [], [],
 		 #include <X11/X.h>
 		 #include "xorg-server.h"])
 
+AC_CHECK_HEADERS([dri3.h], [], [],
+		 [#include <X11/Xmd.h>
+		 #include <xorg-server.h>])
+
 CPPFLAGS="$SAVE_CPPFLAGS"
 
 PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
diff --git a/man/radeon.man b/man/radeon.man
index 7dde040..6e46f89 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -267,6 +267,10 @@ The default value is
 for R/RV6XX, R/RV7XX, RS780, RS880, EVERGREEN, CAYMAN, ARUBA, Southern Islands, and
 Sea Islands.
 .TP
+.BI "Option \*qDRI3\*q \*q" boolean \*q
+Enable the DRI3 extension. The default is
+.B off.
+.TP
 .BI "Option \*qEnablePageFlip\*q \*q" boolean \*q
 Enable DRI2 page flipping.  The default is
 .B on.
diff --git a/src/Makefile.am b/src/Makefile.am
index a3d732a..697c08c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,8 +29,9 @@
 ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
 radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
 
-RADEON_KMS_SRCS=radeon_dri2.c radeon_drm_queue.c radeon_kms.c radeon_present.c \
-	radeon_sync.c radeon_vbo.c radeon_bo_helper.c drmmode_display.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+	radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+	drmmode_display.c
 
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
 	evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
diff --git a/src/radeon.h b/src/radeon.h
index 9346fbd..6084cfe 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -150,6 +150,7 @@ typedef enum {
     OPTION_ZAPHOD_HEADS,
     OPTION_SWAPBUFFERS_WAIT,
     OPTION_DELETE_DP12,
+    OPTION_DRI3,
 } RADEONOpts;
 
 
@@ -549,6 +550,9 @@ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type);
 extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
 				       uint32_t *pitch_offset);
 
+/* radeon_dri3.c */
+Bool radeon_dri3_screen_init(ScreenPtr screen);
+
 /* radeon_present.c */
 Bool radeon_present_screen_init(ScreenPtr screen);
 
diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c
new file mode 100644
index 0000000..83bffae
--- /dev/null
+++ b/src/radeon_dri3.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xorg-server.h"
+#include "xf86.h"
+#include "fb.h"
+
+#ifdef HAVE_DRI3_H
+
+#include "radeon.h"
+#include "radeon_bo_gem.h"
+#include "radeon_glamor.h"
+#include "dri3.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+static int
+radeon_dri3_open_client(ClientPtr client,
+			ScreenPtr screen,
+			RRProviderPtr provider,
+			int *out)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	drm_magic_t magic;
+	int fd;
+
+	fd = open(info->dri2.device_name, 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.
+			 */
+			*out = fd;
+			return Success;
+		} else {
+			close(fd);
+			return BadMatch;
+		}
+	}
+
+	if (drmAuthMagic(info->dri2.drm_fd, magic) < 0) {
+		close(fd);
+		return BadMatch;
+	}
+
+	*out = fd;
+	return Success;
+}
+
+static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen,
+					    int fd,
+					    CARD16 width,
+					    CARD16 height,
+					    CARD16 stride,
+					    CARD8 depth,
+					    CARD8 bpp)
+{
+	PixmapPtr pixmap;
+
+	if (depth < 8)
+		return NULL;
+
+	switch (bpp) {
+	case 8:
+	case 16:
+	case 32:
+		break;
+	default:
+		return NULL;
+	}
+
+	pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
+	if (!pixmap)
+		return NULL;
+
+	if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL))
+		goto free_pixmap;
+
+	if (screen->SetSharedPixmapBacking(pixmap, (void*)(intptr_t)fd))
+		return pixmap;
+
+free_pixmap:
+	fbDestroyPixmap(pixmap);
+	return NULL;
+}
+
+static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
+				      PixmapPtr pixmap,
+				      CARD16 *stride,
+				      CARD32 *size)
+{
+	struct radeon_bo *bo;
+	int fd;
+
+	bo = radeon_get_pixmap_bo(pixmap);
+	if (!bo) {
+#ifdef USE_GLAMOR
+		ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+		RADEONInfoPtr info = RADEONPTR(scrn);
+
+		if (info->use_glamor)
+			return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+#endif
+
+		exaMoveInPixmap(pixmap);
+		bo = radeon_get_pixmap_bo(pixmap);
+		if (!bo)
+			return -1;
+	}
+
+	if (pixmap->devKind > UINT16_MAX)
+		return -1;
+
+	if (radeon_gem_prime_share_bo(bo, &fd) < 0)
+		return -1;
+
+	*stride = pixmap->devKind;
+	*size = bo->size;
+	return fd;
+}
+
+static dri3_screen_info_rec radeon_dri3_screen_info = {
+	.version = 1,
+
+	.open_client = radeon_dri3_open_client,
+	.pixmap_from_fd = radeon_dri3_pixmap_from_fd,
+	.fd_from_pixmap = radeon_dri3_fd_from_pixmap
+};
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+	if (!dri3_screen_init(screen, &radeon_dri3_screen_info)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "dri3_screen_init failed\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+#else /* !HAVE_DRI3_H */
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+	xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+		   "Can't initialize DRI3 because dri3.h not available at "
+		   "build time\n");
+
+	return FALSE;
+}
+
+#endif
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index f4452bc..b32086e 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -76,6 +76,7 @@ const OptionInfoRec RADEONOptions_KMS[] = {
     { OPTION_ZAPHOD_HEADS,   "ZaphodHeads",      OPTV_STRING,  {0}, FALSE },
     { OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_DELETE_DP12,    "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
+    { OPTION_DRI3,           "DRI3",             OPTV_BOOLEAN, {0}, FALSE },
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
@@ -1230,6 +1231,8 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
     ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr  info  = RADEONPTR(pScrn);
     int            subPixelOrder = SubPixelUnknown;
+    MessageType from;
+    Bool have_present = FALSE, value;
     const char *s;
     void *front_ptr;
 
@@ -1341,7 +1344,23 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 #endif
 
     if (radeon_sync_init(pScreen))
-	radeon_present_screen_init(pScreen);
+	have_present = radeon_present_screen_init(pScreen);
+
+    if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
+	from = X_CONFIG;
+    else
+	from = X_DEFAULT;
+
+    if (value) {
+	if (have_present)
+	    value = radeon_dri3_screen_init(pScreen);
+	else
+	    value = FALSE;
+
+	if (!value)
+	    from = X_WARNING;
+    }
+    xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
 
     pScrn->vtSema = TRUE;
     xf86SetBackingStore(pScreen);
-- 
2.1.4



More information about the xorg-driver-ati mailing list