2025-05-10 21:49:39 +08:00

201 lines
5.6 KiB
C

/*
* Copyright (c) 2020, Fuzhou Rockchip Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifdef HAVE_DIX_CONFIG_H
#include "dix-config.h"
#endif
#include <unistd.h>
#include <fcntl.h>
#include <drm_fourcc.h>
#include "xf86.h"
#include "dri3.h"
#include "driver.h"
/* Based on glamor/glamor_egl.c#glamor_dri3_open_client */
static int
ms_exa_dri3_open_client(ClientPtr client,
ScreenPtr screen,
RRProviderPtr provider,
int *fdp)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
int fd;
drm_magic_t magic;
fd = open(ms->drmmode.dri3_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.
*/
*fdp = fd;
return Success;
} else {
close(fd);
return BadMatch;
}
}
if (drmAuthMagic(ms->drmmode.fd, magic) < 0) {
close(fd);
return BadMatch;
}
*fdp = fd;
return Success;
}
static PixmapPtr
ms_exa_pixmap_from_fds(ScreenPtr screen,
CARD8 num_fds, const int *fds,
CARD16 width, CARD16 height,
const CARD32 *strides, const CARD32 *offsets,
CARD8 depth, CARD8 bpp,
uint64_t modifier)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
PixmapPtr pixmap;
struct dumb_bo *bo;
if (num_fds != 1 || offsets[0] || modifier != DRM_FORMAT_MOD_INVALID)
return NULL;
pixmap = drmmode_create_pixmap_header(screen, width, height,
depth, bpp, strides[0], NULL);
if (!pixmap)
return NULL;
bo = dumb_get_bo_from_fd(ms->drmmode.fd, fds[0],
strides[0], strides[0] * height);
if (!bo)
goto err_free_pixmap;
if (!ms_exa_set_pixmap_bo(scrn, pixmap, bo, TRUE))
goto err_free_bo;
return pixmap;
err_free_bo:
dumb_bo_destroy(ms->drmmode.fd, bo);
err_free_pixmap:
screen->DestroyPixmap(pixmap);
return NULL;
}
static int
ms_exa_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
CARD16 *stride, CARD32 *size)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
struct dumb_bo *bo;
int fd;
bo = ms_exa_bo_from_pixmap(screen, pixmap);
if (!bo)
return -1;
fd = dumb_bo_get_fd(ms->drmmode.fd, bo, 0);
*stride = bo->pitch;
*size = bo->size;
return fd;
}
static int
ms_exa_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
uint32_t *strides, uint32_t *offsets,
uint64_t *modifier)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
struct dumb_bo *bo;
bo = ms_exa_bo_from_pixmap(screen, pixmap);
if (!bo)
return 0;
fds[0] = dumb_bo_get_fd(ms->drmmode.fd, bo, 0);
strides[0] = bo->pitch;
offsets[0] = 0;
*modifier = DRM_FORMAT_MOD_INVALID;
return 1;
}
static Bool
ms_exa_get_formats(ScreenPtr screen,
CARD32 *num_formats, CARD32 **formats)
{
/* TODO: Return formats */
*num_formats = 0;
return TRUE;
}
static Bool
ms_exa_get_modifiers(ScreenPtr screen, uint32_t format,
uint32_t *num_modifiers, uint64_t **modifiers)
{
*num_modifiers = 0;
return TRUE;
}
static Bool
ms_exa_get_drawable_modifiers(DrawablePtr draw, uint32_t format,
uint32_t *num_modifiers, uint64_t **modifiers)
{
*num_modifiers = 0;
return TRUE;
}
static const dri3_screen_info_rec ms_exa_dri3_info = {
.version = 2,
.open_client = ms_exa_dri3_open_client,
.pixmap_from_fds = ms_exa_pixmap_from_fds,
.fd_from_pixmap = ms_exa_egl_fd_from_pixmap,
.fds_from_pixmap = ms_exa_egl_fds_from_pixmap,
.get_formats = ms_exa_get_formats,
.get_modifiers = ms_exa_get_modifiers,
.get_drawable_modifiers = ms_exa_get_drawable_modifiers,
};
Bool
ms_exa_dri3_init(ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
ms->drmmode.dri3_device_name = drmGetDeviceNameFromFd2(ms->drmmode.fd);
return dri3_screen_init(screen, &ms_exa_dri3_info);
}