mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-25 23:45:58 +01:00
screencast: create gbm device
This is done by using the first device returned by getDRMDevices2 containing a render node (DRM_NODE_RENDER).
This commit is contained in:
parent
7c7cb88d8f
commit
9d620273e5
4 changed files with 62 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
#ifndef SCREENCAST_COMMON_H
|
#ifndef SCREENCAST_COMMON_H
|
||||||
#define SCREENCAST_COMMON_H
|
#define SCREENCAST_COMMON_H
|
||||||
|
|
||||||
|
#include <gbm.h>
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
|
@ -103,6 +104,9 @@ struct xdpw_screencast_context {
|
||||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
|
|
||||||
|
// gbm
|
||||||
|
struct gbm_device *gbm;
|
||||||
|
|
||||||
// sessions
|
// sessions
|
||||||
struct wl_list screencast_instances;
|
struct wl_list screencast_instances;
|
||||||
};
|
};
|
||||||
|
@ -158,6 +162,7 @@ struct xdpw_wlr_output {
|
||||||
};
|
};
|
||||||
|
|
||||||
void randname(char *buf);
|
void randname(char *buf);
|
||||||
|
struct gbm_device *xdpw_gbm_device_create(void);
|
||||||
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
||||||
enum buffer_type buffer_type, struct xdpw_screencopy_frame_info *frame_info);
|
enum buffer_type buffer_type, struct xdpw_screencopy_frame_info *frame_info);
|
||||||
void xdpw_buffer_destroy(struct xdpw_buffer *buffer);
|
void xdpw_buffer_destroy(struct xdpw_buffer *buffer);
|
||||||
|
|
|
@ -27,6 +27,8 @@ pipewire = dependency('libpipewire-0.3', version: '>= 0.3.41')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
|
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
|
||||||
iniparser = dependency('inih')
|
iniparser = dependency('inih')
|
||||||
|
gbm = dependency('gbm')
|
||||||
|
drm = dependency('libdrm')
|
||||||
|
|
||||||
epoll = dependency('', required: false)
|
epoll = dependency('', required: false)
|
||||||
if (not cc.has_function('timerfd_create', prefix: '#include <sys/timerfd.h>') or
|
if (not cc.has_function('timerfd_create', prefix: '#include <sys/timerfd.h>') or
|
||||||
|
@ -92,6 +94,8 @@ executable(
|
||||||
pipewire,
|
pipewire,
|
||||||
rt,
|
rt,
|
||||||
iniparser,
|
iniparser,
|
||||||
|
gbm,
|
||||||
|
drm,
|
||||||
epoll,
|
epoll,
|
||||||
],
|
],
|
||||||
include_directories: [inc],
|
include_directories: [inc],
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <libdrm/drm_fourcc.h>
|
||||||
|
#include <xf86drm.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#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) {
|
static int anonymous_shm_open(void) {
|
||||||
char name[] = "/xdpw-shm-XXXXXX";
|
char name[] = "/xdpw-shm-XXXXXX";
|
||||||
int retries = 100;
|
int retries = 100;
|
||||||
|
|
|
@ -641,6 +641,12 @@ int xdpw_wlr_screencopy_init(struct xdpw_state *state) {
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,6 +672,11 @@ void xdpw_wlr_screencopy_finish(struct xdpw_screencast_context *ctx) {
|
||||||
if (ctx->xdg_output_manager) {
|
if (ctx->xdg_output_manager) {
|
||||||
zxdg_output_manager_v1_destroy(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) {
|
if (ctx->registry) {
|
||||||
wl_registry_destroy(ctx->registry);
|
wl_registry_destroy(ctx->registry);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue