xwayland/glamor/gbm: make wl_drm optional

Build on top of [1] to use linux-dmabuf to grab the main device
when wl_drm is unavailable. Fixes Xwayland glamor on top of latest
wlroots commit which has dropped wl_drm support [2].

[1]: https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/818
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4397

Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Simon Ser 2024-01-08 11:32:27 +01:00 committed by Olivier Fourdan
parent 4beb4f26ef
commit d7f1909e7c

View File

@ -56,13 +56,15 @@ struct xwl_gbm_private {
drmDevice *device; drmDevice *device;
char *device_name; char *device_name;
struct gbm_device *gbm; struct gbm_device *gbm;
struct wl_drm *drm;
int drm_fd; int drm_fd;
Bool fd_render_node; Bool fd_render_node;
Bool drm_authenticated; Bool drm_authenticated;
uint32_t capabilities;
Bool dmabuf_capable; Bool dmabuf_capable;
Bool glamor_gles; Bool glamor_gles;
/* Set if wl_drm is available */
struct wl_drm *drm;
uint32_t capabilities;
}; };
struct xwl_pixmap { struct xwl_pixmap {
@ -562,7 +564,8 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
zwp_linux_buffer_params_v1_create_immed(params, width, height, zwp_linux_buffer_params_v1_create_immed(params, width, height,
format, 0); format, 0);
zwp_linux_buffer_params_v1_destroy(params); zwp_linux_buffer_params_v1_destroy(params);
} else if (num_planes == 1 && modifier == DRM_FORMAT_MOD_INVALID) { } else if (num_planes == 1 && modifier == DRM_FORMAT_MOD_INVALID &&
xwl_gbm->drm) {
xwl_pixmap->buffer = xwl_pixmap->buffer =
wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fds[0], width, height, wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fds[0], width, height,
format, format,
@ -1028,8 +1031,8 @@ xwl_glamor_gbm_has_wl_interfaces(struct xwl_screen *xwl_screen)
{ {
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
if (xwl_gbm->drm == NULL) { if (xwl_gbm->drm == NULL && xwl_screen->dmabuf_protocol_version < 4) {
LogMessageVerb(X_INFO, 3, "glamor: 'wl_drm' not supported\n"); LogMessageVerb(X_INFO, 3, "glamor: 'wl_drm' not supported and linux-dmabuf v4 not supported\n");
return FALSE; return FALSE;
} }
@ -1133,6 +1136,47 @@ xwl_glamor_try_gles_api(struct xwl_screen *xwl_screen)
return TRUE; return TRUE;
} }
static Bool
xwl_glamor_gbm_init_main_dev(struct xwl_screen *xwl_screen)
{
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
drmDevice *main_dev;
while (!xwl_screen->default_feedback.feedback_done) {
if (wl_display_dispatch(xwl_screen->display) < 0) {
ErrorF("Failed to dispatch Wayland display\n");
return FALSE;
}
}
main_dev = xwl_screen->default_feedback.main_dev;
if (!(main_dev->available_nodes & (1 << DRM_NODE_RENDER))) {
ErrorF("Main linux-dmabuf device has no render node\n");
return FALSE;
}
xwl_gbm->device_name = strdup(main_dev->nodes[DRM_NODE_RENDER]);
if (!xwl_gbm->device_name) {
return FALSE;
}
xwl_gbm->drm_fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC);
if (xwl_gbm->drm_fd < 0) {
ErrorF("wayland-egl: could not open %s (%s)\n",
xwl_gbm->device_name, strerror(errno));
return FALSE;
}
if (drmGetDevice2(xwl_gbm->drm_fd, 0, &xwl_gbm->device) != 0) {
ErrorF("wayland-egl: Could not fetch DRM device %s\n",
xwl_gbm->device_name);
return FALSE;
}
xwl_gbm->fd_render_node = TRUE;
return TRUE;
}
static Bool static Bool
xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen) xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
{ {
@ -1141,6 +1185,9 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
const GLubyte *renderer; const GLubyte *renderer;
const char *gbm_backend_name; const char *gbm_backend_name;
if (!xwl_gbm->drm && !xwl_glamor_gbm_init_main_dev(xwl_screen))
return FALSE;
if (!xwl_gbm->fd_render_node && !xwl_gbm->drm_authenticated) { if (!xwl_gbm->fd_render_node && !xwl_gbm->drm_authenticated) {
ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n"); ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
return FALSE; return FALSE;