From 9d620273e5f5bc358e7d8521f2652eaf8715b5f3 Mon Sep 17 00:00:00 2001 From: columbarius Date: Tue, 22 Jun 2021 03:07:51 +0200 Subject: [PATCH] screencast: create gbm device This is done by using the first device returned by getDRMDevices2 containing a render node (DRM_NODE_RENDER). --- include/screencast_common.h | 5 ++++ meson.build | 4 +++ src/screencast/screencast_common.c | 42 ++++++++++++++++++++++++++++++ src/screencast/wlr_screencast.c | 11 ++++++++ 4 files changed, 62 insertions(+) diff --git a/include/screencast_common.h b/include/screencast_common.h index a196761..2b16b09 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -1,6 +1,7 @@ #ifndef SCREENCAST_COMMON_H #define SCREENCAST_COMMON_H +#include #include #include #include @@ -103,6 +104,9 @@ struct xdpw_screencast_context { struct zxdg_output_manager_v1 *xdg_output_manager; struct wl_shm *shm; + // gbm + struct gbm_device *gbm; + // sessions struct wl_list screencast_instances; }; @@ -158,6 +162,7 @@ struct xdpw_wlr_output { }; void randname(char *buf); +struct gbm_device *xdpw_gbm_device_create(void); struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast, enum buffer_type buffer_type, struct xdpw_screencopy_frame_info *frame_info); void xdpw_buffer_destroy(struct xdpw_buffer *buffer); diff --git a/meson.build b/meson.build index f611c58..50665de 100644 --- a/meson.build +++ b/meson.build @@ -27,6 +27,8 @@ pipewire = dependency('libpipewire-0.3', version: '>= 0.3.41') wayland_client = dependency('wayland-client') wayland_protos = dependency('wayland-protocols', version: '>=1.14') iniparser = dependency('inih') +gbm = dependency('gbm') +drm = dependency('libdrm') epoll = dependency('', required: false) if (not cc.has_function('timerfd_create', prefix: '#include ') or @@ -92,6 +94,8 @@ executable( pipewire, rt, iniparser, + gbm, + drm, epoll, ], include_directories: [inc], diff --git a/src/screencast/screencast_common.c b/src/screencast/screencast_common.c index 0b1ecfe..10a6097 100644 --- a/src/screencast/screencast_common.c +++ b/src/screencast/screencast_common.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "logger.h" @@ -20,6 +21,47 @@ void randname(char *buf) { } } +static char *gbm_find_render_node() { + drmDevice *devices[64]; + char *render_node = NULL; + + int n = drmGetDevices2(0, devices, sizeof(devices) / sizeof(devices[0])); + for (int i = 0; i < n; ++i) { + drmDevice *dev = devices[i]; + if (!(dev->available_nodes & (1 << DRM_NODE_RENDER))) + continue; + + render_node = strdup(dev->nodes[DRM_NODE_RENDER]); + break; + } + + drmFreeDevices(devices, n); + return render_node; +} + +struct gbm_device *xdpw_gbm_device_create(void) { + struct gbm_device *gbm; + char *render_node = NULL; + + render_node = gbm_find_render_node(); + if (render_node == NULL) { + logprint(ERROR, "xdpw: Could not find render node"); + return NULL; + } + logprint(INFO, "xdpw: Using render node %s", render_node); + + int fd = open(render_node, O_RDWR | O_CLOEXEC); + if (fd < 0) { + logprint(ERROR, "xdpw: Could not open render node %s", render_node); + free(render_node); + return NULL; + } + + free(render_node); + gbm = gbm_create_device(fd); + return gbm; +} + static int anonymous_shm_open(void) { char name[] = "/xdpw-shm-XXXXXX"; int retries = 100; diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 1c585a8..cc10f6e 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -641,6 +641,12 @@ int xdpw_wlr_screencopy_init(struct xdpw_state *state) { return -1; } + // make sure we have a gbm device + ctx->gbm = xdpw_gbm_device_create(); + if (!ctx->gbm) { + logprint(ERROR, "System doesn't support gbm!"); + } + return 0; } @@ -666,6 +672,11 @@ void xdpw_wlr_screencopy_finish(struct xdpw_screencast_context *ctx) { if (ctx->xdg_output_manager) { zxdg_output_manager_v1_destroy(ctx->xdg_output_manager); } + if (ctx->gbm) { + int fd = gbm_device_get_fd(ctx->gbm); + gbm_device_destroy(ctx->gbm); + close(fd); + } if (ctx->registry) { wl_registry_destroy(ctx->registry); }