

index 71d8ff09..acd9fe0d 100644

--- a/

+++ b/ diff --git a/configure.ac b/configure.acindex 71d8ff09..acd9fe0d 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])

index 7dde0400..6e46f894 100644

--- a/

+++ b/ diff --git a/man/radeon.man b/man/radeon.manindex 7dde0400..6e46f894 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.

index a3d732a1..697c08c5 100644

--- a/

+++ b/ diff --git a/src/Makefile.am b/src/Makefile.amindex a3d732a1..697c08c5 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

index 9346fbd6..6084cfed 100644

--- a/

+++ b/ diff --git a/src/radeon.h b/src/radeon.hindex 9346fbd6..6084cfed 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);

new file mode 100644

index 00000000..83bffaea

--- /dev/null

+++ b/ diff --git a/src/radeon_dri3.c b/src/radeon_dri3.cnew file mode 100644index 00000000..83bffaea--- /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

"); + 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

"); + + return FALSE; +} + +#endif

index f4452bc9..b32086e1 100644

--- a/

+++ b/ diff --git a/src/radeon_kms.c b/src/radeon_kms.cindex f4452bc9..b32086e1 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

", value ? "en" : "dis"); pScrn->vtSema = TRUE; xf86SetBackingStore(pScreen);