From 048b8d21ecbd1168ff8e033b12cbfd66bba0127c Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 15 Jul 2024 18:57:33 +0200 Subject: Add support for desktop portal capture (-w portal) --- include/capture/portal.h | 16 ++++++++++ include/dbus.h | 43 +++++++++++++++++++++++++ include/egl.h | 7 ++-- include/pipewire.h | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ include/utils.h | 5 ++- 5 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 include/capture/portal.h create mode 100644 include/dbus.h create mode 100644 include/pipewire.h (limited to 'include') diff --git a/include/capture/portal.h b/include/capture/portal.h new file mode 100644 index 0000000..989b042 --- /dev/null +++ b/include/capture/portal.h @@ -0,0 +1,16 @@ +#ifndef GSR_CAPTURE_PORTAL_H +#define GSR_CAPTURE_PORTAL_H + +#include "capture.h" + +typedef struct { + gsr_egl *egl; + gsr_color_range color_range; + bool hdr; + bool record_cursor; + bool restore_portal_session; +} gsr_capture_portal_params; + +gsr_capture* gsr_capture_portal_create(const gsr_capture_portal_params *params); + +#endif /* GSR_CAPTURE_PORTAL_H */ diff --git a/include/dbus.h b/include/dbus.h new file mode 100644 index 0000000..95c3732 --- /dev/null +++ b/include/dbus.h @@ -0,0 +1,43 @@ +#ifndef GSR_DBUS_H +#define GSR_DBUS_H + +#include +#include +#include + +#define DBUS_RANDOM_STR_SIZE 16 + +typedef struct { + DBusConnection *con; + DBusError err; + char random_str[DBUS_RANDOM_STR_SIZE + 1]; + unsigned int handle_counter; + bool desktop_portal_rule_added; + uint32_t screencast_version; + char *screencast_restore_token; +} gsr_dbus; + +typedef enum { + GSR_PORTAL_CAPTURE_TYPE_MONITOR = 1 << 0, + GSR_PORTAL_CAPTURE_TYPE_WINDOW = 1 << 1, + GSR_PORTAL_CAPTURE_TYPE_VIRTUAL = 1 << 2, + GSR_PORTAL_CAPTURE_TYPE_ALL = GSR_PORTAL_CAPTURE_TYPE_MONITOR | GSR_PORTAL_CAPTURE_TYPE_WINDOW | GSR_PORTAL_CAPTURE_TYPE_VIRTUAL +} gsr_portal_capture_type; + +typedef enum { + GSR_PORTAL_CURSOR_MODE_HIDDEN = 1 << 0, + GSR_PORTAL_CURSOR_MODE_EMBEDDED = 1 << 1, + GSR_PORTAL_CURSOR_MODE_METADATA = 1 << 2 +} gsr_portal_cursor_mode; + +/* Blocking. TODO: Make non-blocking */ +bool gsr_dbus_init(gsr_dbus *self, const char *screencast_restore_token); +void gsr_dbus_deinit(gsr_dbus *self); + +bool gsr_dbus_screencast_create_session(gsr_dbus *self, char **session_handle); +bool gsr_dbus_screencast_select_sources(gsr_dbus *self, const char *session_handle, gsr_portal_capture_type capture_type, gsr_portal_cursor_mode cursor_mode); +bool gsr_dbus_screencast_start(gsr_dbus *self, const char *session_handle, uint32_t *pipewire_node); +bool gsr_dbus_screencast_open_pipewire_remote(gsr_dbus *self, const char *session_handle, int *pipewire_fd); +const char* gsr_dbus_screencast_get_restore_token(gsr_dbus *self); + +#endif /* GSR_DBUS_H */ diff --git a/include/egl.h b/include/egl.h index 899c0d0..1bf3535 100644 --- a/include/egl.h +++ b/include/egl.h @@ -78,9 +78,9 @@ typedef void(*__GLXextFuncPtr)(void); #define GL_TEXTURE_2D 0x0DE1 #define GL_TEXTURE_EXTERNAL_OES 0x8D65 #define GL_RED 0x1903 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_ALPHA 0x1906 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 #define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 #define GL_RG 0x8227 #define GL_RGB 0x1907 @@ -236,6 +236,7 @@ struct gsr_egl { void (*glTexParameteriv)(unsigned int target, unsigned int pname, const int *params); void (*glGetTexLevelParameteriv)(unsigned int target, int level, unsigned int pname, int *params); void (*glTexImage2D)(unsigned int target, int level, int internalFormat, int width, int height, int border, unsigned int format, unsigned int type, const void *pixels); + void (*glTexSubImage2D)(unsigned int target, int level, int xoffset, int yoffset, int width, int height, unsigned int format, unsigned int type, const void *pixels); void (*glCopyImageSubData)(unsigned int srcName, unsigned int srcTarget, int srcLevel, int srcX, int srcY, int srcZ, unsigned int dstName, unsigned int dstTarget, int dstLevel, int dstX, int dstY, int dstZ, int srcWidth, int srcHeight, int srcDepth); void (*glClearTexImage)(unsigned int texture, unsigned int level, unsigned int format, unsigned int type, const void *data); void (*glGetTexImage)(unsigned int target, int level, unsigned int format, unsigned int type, void *pixels); diff --git a/include/pipewire.h b/include/pipewire.h new file mode 100644 index 0000000..cea61a1 --- /dev/null +++ b/include/pipewire.h @@ -0,0 +1,83 @@ +#ifndef GSR_PIPEWIRE_H +#define GSR_PIPEWIRE_H + +#include +#include +#include + +#include +#include + +typedef struct gsr_egl gsr_egl; + +typedef struct { + int major; + int minor; + int micro; +} gsr_pipewire_data_version; + +typedef struct { + uint32_t fps_num; + uint32_t fps_den; +} gsr_pipewire_video_info; + +typedef struct { + int fd; + uint32_t offset; + int32_t stride; +} gsr_pipewire_dmabuf_data; + +typedef struct { + int x, y; + int width, height; +} gsr_pipewire_region; + +typedef struct { + gsr_egl *egl; + int fd; + uint32_t node; + pthread_mutex_t mutex; + bool mutex_initialized; + + struct pw_thread_loop *thread_loop; + struct pw_context *context; + struct pw_core *core; + struct spa_hook core_listener; + struct pw_stream *stream; + struct spa_hook stream_listener; + struct spa_source *reneg; + struct spa_video_info format; + int server_version_sync; + bool negotiated; + + struct { + bool visible; + bool valid; + uint8_t *data; + int x, y; + int hotspot_x, hotspot_y; + int width, height; + } cursor; + + struct { + bool valid; + int x, y; + uint32_t width, height; + } crop; + + gsr_pipewire_data_version server_version; + gsr_pipewire_video_info video_info; + gsr_pipewire_dmabuf_data dmabuf_data; +} gsr_pipewire; + +/* + |capture_cursor| only applies to when capturing a window or region. + In other cases |pipewire_node|'s setup will determine if the cursor is included. + Note that the cursor is not guaranteed to be shown even if set to true, it depends on the wayland compositor. +*/ +bool gsr_pipewire_init(gsr_pipewire *self, int pipewire_fd, uint32_t pipewire_node, int fps, bool capture_cursor, gsr_egl *egl); +void gsr_pipewire_deinit(gsr_pipewire *self); + +bool gsr_pipewire_map_texture(gsr_pipewire *self, unsigned int texture_id, unsigned int cursor_texture_id, gsr_pipewire_region *region, gsr_pipewire_region *cursor_region); + +#endif /* GSR_PIPEWIRE_H */ diff --git a/include/utils.h b/include/utils.h index c5d659a..c08b3f6 100644 --- a/include/utils.h +++ b/include/utils.h @@ -6,7 +6,8 @@ #include "../include/defs.h" #include #include -#include + +typedef struct _XRRCrtcInfo XRRCrtcInfo; typedef struct { const char *name; @@ -41,4 +42,6 @@ bool gsr_get_valid_card_path(gsr_egl *egl, char *output, bool is_monitor_capture /* |render_path| should be at least 128 bytes in size */ bool gsr_card_path_get_render_path(const char *card_path, char *render_path); +int create_directory_recursive(char *path); + #endif /* GSR_UTILS_H */ -- cgit v1.2.3