summaryrefslogtreecommitdiff
path: root/src/amdgpu_dri3.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2015-06-02 17:04:21 +0900
committerMichel Dänzer <michel@daenzer.net>2015-06-08 17:59:55 +0900
commitedfff6b1a3a19953644b8052b30076f76f7dc337 (patch)
treec7309040a1f5d3657c88b40b6948cbaa55567837 /src/amdgpu_dri3.c
parentd295b5b3310bc5c23d232c4be4170165a057c090 (diff)
Add DRI3 support
Must be enabled with Option "DRI3" in xorg.conf. (Cherry picked from radeon commits 64e1e4dbdd3caee6f5d8f6b6c094b4533fa94953, 694e04720b886060fe3eefdce59741f218c8269f, f940fd741b15f03393037c5bb904cd74f012de9d, fcd37f65f485291084c174666bd605e215bf1398, 4b0997e56dec0053cb2cb793e0f4ae35055ff7e6, f68d9b5ba0c91a725b5eec9386c61bea8824c299 and 98fb4199e63fedd4607cddee64bf602d6398df81) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src/amdgpu_dri3.c')
-rw-r--r--src/amdgpu_dri3.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/amdgpu_dri3.c b/src/amdgpu_dri3.c
new file mode 100644
index 0000000..ce0f8e7
--- /dev/null
+++ b/src/amdgpu_dri3.c
@@ -0,0 +1,196 @@
+/*
+ * 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 "amdgpu_drv.h"
+
+#ifdef HAVE_DRI3_H
+
+#include "amdgpu_glamor.h"
+#include "amdgpu_pixmap.h"
+#include "dri3.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+static int
+amdgpu_dri3_open(ScreenPtr screen, RRProviderPtr provider, int *out)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ AMDGPUInfoPtr info = AMDGPUPTR(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 amdgpu_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 = screen->CreatePixmap(screen, 0, 0, depth, 0);
+ if (!pixmap)
+ return NULL;
+
+ if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, bpp, stride,
+ NULL))
+ goto free_pixmap;
+
+ if (screen->SetSharedPixmapBacking(pixmap, (void*)(intptr_t)fd))
+ return pixmap;
+
+free_pixmap:
+ fbDestroyPixmap(pixmap);
+ return NULL;
+}
+
+static int amdgpu_dri3_fd_from_pixmap(ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride,
+ CARD32 *size)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+ struct amdgpu_buffer *bo;
+ struct amdgpu_bo_info bo_info;
+ uint32_t fd;
+
+#ifdef USE_GLAMOR
+ if (info->use_glamor)
+ return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+#endif
+
+ bo = amdgpu_get_pixmap_bo(pixmap);
+ if (!bo)
+ return -1;
+
+ if (pixmap->devKind > UINT16_MAX)
+ return -1;
+
+ if (amdgpu_bo_query_info(bo->bo.amdgpu, &bo_info) != 0)
+ return -1;
+
+ if (amdgpu_bo_export(bo->bo.amdgpu, amdgpu_bo_handle_type_dma_buf_fd,
+ &fd) != 0)
+ return -1;
+
+ *stride = pixmap->devKind;
+ *size = bo_info.alloc_size;
+ return fd;
+}
+
+static dri3_screen_info_rec amdgpu_dri3_screen_info = {
+ .version = 0,
+
+ .open = amdgpu_dri3_open,
+ .pixmap_from_fd = amdgpu_dri3_pixmap_from_fd,
+ .fd_from_pixmap = amdgpu_dri3_fd_from_pixmap
+};
+
+Bool
+amdgpu_dri3_screen_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ if (!dri3_screen_init(screen, &amdgpu_dri3_screen_info)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "dri3_screen_init failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#else /* !HAVE_DRI3_H */
+
+Bool
+amdgpu_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