diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2015-06-02 17:04:21 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2015-06-08 17:59:55 +0900 |
commit | edfff6b1a3a19953644b8052b30076f76f7dc337 (patch) | |
tree | c7309040a1f5d3657c88b40b6948cbaa55567837 /src/amdgpu_dri3.c | |
parent | d295b5b3310bc5c23d232c4be4170165a057c090 (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.c | 196 |
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 |