From 1e62e654e2bd511b27ff519ca833f651479f6ee3 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 20 Jul 2025 22:04:54 +0200 Subject: [PATCH] Pipewire: support alpha textures again, do alpha blending and clear background if fourcc is alpha. --- include/pipewire_video.h | 2 +- meson.build | 2 +- project.conf | 2 +- src/capture/portal.c | 19 ++++++++++++++++--- src/pipewire_video.c | 35 +++++++++++++++++++---------------- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/include/pipewire_video.h b/include/pipewire_video.h index d98e43d..5a371b4 100644 --- a/include/pipewire_video.h +++ b/include/pipewire_video.h @@ -9,7 +9,7 @@ #include #define GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS 1024 -#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 6 +#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 12 #define GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES 4 typedef struct gsr_egl gsr_egl; diff --git a/meson.build b/meson.build index 4ba7dc3..2cc98c3 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('gpu-screen-recorder', ['c', 'cpp'], version : '5.6.1', default_options : ['warning_level=2']) +project('gpu-screen-recorder', ['c', 'cpp'], version : '5.6.2', default_options : ['warning_level=2']) add_project_arguments('-Wshadow', language : ['c', 'cpp']) if get_option('buildtype') == 'debug' diff --git a/project.conf b/project.conf index de715f1..404d949 100644 --- a/project.conf +++ b/project.conf @@ -1,7 +1,7 @@ [package] name = "gpu-screen-recorder" type = "executable" -version = "5.6.1" +version = "5.6.2" platforms = ["posix"] [config] diff --git a/src/capture/portal.c b/src/capture/portal.c index d2217d1..088ddf6 100644 --- a/src/capture/portal.c +++ b/src/capture/portal.c @@ -319,6 +319,15 @@ static bool gsr_capture_portal_capture_has_synchronous_task(gsr_capture *cap) { return gsr_pipewire_video_should_restart(&self->pipewire); } +static bool fourcc_has_alpha(uint32_t fourcc) { + const uint8_t *p = (const uint8_t*)&fourcc; + for(int i = 0; i < 4; ++i) { + if(p[i] == 'A') + return true; + } + return false; +} + static int gsr_capture_portal_capture(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion) { (void)color_conversion; gsr_capture_portal *self = cap->priv; @@ -361,10 +370,14 @@ static int gsr_capture_portal_capture(gsr_capture *cap, gsr_capture_metadata *ca // TODO: Handle region crop + const bool fourcc_alpha = fourcc_has_alpha(self->pipewire_fourcc); + if(fourcc_alpha) + gsr_color_conversion_clear(color_conversion); + gsr_color_conversion_draw(color_conversion, self->using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id, - target_pos, output_size, - (vec2i){self->region.x, self->region.y}, self->capture_size, self->capture_size, - GSR_ROT_0, GSR_SOURCE_COLOR_RGB, self->using_external_image, false); + target_pos, output_size, + (vec2i){self->region.x, self->region.y}, self->capture_size, self->capture_size, + GSR_ROT_0, GSR_SOURCE_COLOR_RGB, self->using_external_image, fourcc_alpha); if(self->params.record_cursor && self->texture_map.cursor_texture_id > 0 && self->cursor_region.width > 0) { const vec2d scale = { diff --git a/src/pipewire_video.c b/src/pipewire_video.c index 54500fc..3c3566a 100644 --- a/src/pipewire_video.c +++ b/src/pipewire_video.c @@ -354,17 +354,17 @@ static int64_t spa_video_format_to_drm_format(const enum spa_video_format format switch(format) { case SPA_VIDEO_FORMAT_RGBx: return DRM_FORMAT_XBGR8888; case SPA_VIDEO_FORMAT_BGRx: return DRM_FORMAT_XRGB8888; - // case SPA_VIDEO_FORMAT_RGBA: return DRM_FORMAT_ABGR8888; - //case SPA_VIDEO_FORMAT_BGRA: return DRM_FORMAT_ARGB8888; + case SPA_VIDEO_FORMAT_RGBA: return DRM_FORMAT_ABGR8888; + case SPA_VIDEO_FORMAT_BGRA: return DRM_FORMAT_ARGB8888; case SPA_VIDEO_FORMAT_RGB: return DRM_FORMAT_XBGR8888; case SPA_VIDEO_FORMAT_BGR: return DRM_FORMAT_XRGB8888; - //case SPA_VIDEO_FORMAT_ARGB: return DRM_FORMAT_XRGB8888; - //case SPA_VIDEO_FORMAT_ABGR: return DRM_FORMAT_XRGB8888; + case SPA_VIDEO_FORMAT_ARGB: return DRM_FORMAT_BGRA8888; + case SPA_VIDEO_FORMAT_ABGR: return DRM_FORMAT_RGBA8888; #if PW_CHECK_VERSION(0, 3, 41) case SPA_VIDEO_FORMAT_xRGB_210LE: return DRM_FORMAT_XRGB2101010; case SPA_VIDEO_FORMAT_xBGR_210LE: return DRM_FORMAT_XBGR2101010; - // case SPA_VIDEO_FORMAT_ARGB_210LE: return DRM_FORMAT_ARGB2101010; - // case SPA_VIDEO_FORMAT_ABGR_210LE: return DRM_FORMAT_ABGR2101010; + case SPA_VIDEO_FORMAT_ARGB_210LE: return DRM_FORMAT_ARGB2101010; + case SPA_VIDEO_FORMAT_ABGR_210LE: return DRM_FORMAT_ABGR2101010; #endif default: break; } @@ -374,24 +374,24 @@ static int64_t spa_video_format_to_drm_format(const enum spa_video_format format #if PW_CHECK_VERSION(0, 3, 41) #define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS #else -#define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS 4 +#define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS 8 #endif static const enum spa_video_format video_formats[GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS] = { - // SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_BGR, SPA_VIDEO_FORMAT_RGBx, - // SPA_VIDEO_FORMAT_RGBA, SPA_VIDEO_FORMAT_RGB, - // SPA_VIDEO_FORMAT_ARGB, - // SPA_VIDEO_FORMAT_ABGR, #if PW_CHECK_VERSION(0, 3, 41) SPA_VIDEO_FORMAT_xRGB_210LE, SPA_VIDEO_FORMAT_xBGR_210LE, - // SPA_VIDEO_FORMAT_ARGB_210LE, - // SPA_VIDEO_FORMAT_ABGR_210LE + SPA_VIDEO_FORMAT_ARGB_210LE, + SPA_VIDEO_FORMAT_ABGR_210LE, #endif + SPA_VIDEO_FORMAT_RGBA, + SPA_VIDEO_FORMAT_BGRA, + SPA_VIDEO_FORMAT_ARGB, + SPA_VIDEO_FORMAT_ABGR, }; static bool gsr_pipewire_video_build_format_params(gsr_pipewire_video *self, struct spa_pod_builder *pod_builder, struct spa_pod **params, uint32_t *num_params) { @@ -446,6 +446,8 @@ static bool spa_video_format_get_modifiers(gsr_pipewire_video *self, const enum //modifiers[0] = DRM_FORMAT_MOD_LINEAR; //modifiers[1] = DRM_FORMAT_MOD_INVALID; //*num_modifiers = 2; + modifiers[0] = DRM_FORMAT_MOD_INVALID; + *num_modifiers = 1; return false; } @@ -460,7 +462,8 @@ static bool spa_video_format_get_modifiers(gsr_pipewire_video *self, const enum //modifiers[0] = DRM_FORMAT_MOD_LINEAR; //modifiers[1] = DRM_FORMAT_MOD_INVALID; //*num_modifiers = 2; - *num_modifiers = 0; + modifiers[0] = DRM_FORMAT_MOD_INVALID; + *num_modifiers = 1; return false; } @@ -730,9 +733,9 @@ static EGLImage gsr_pipewire_video_create_egl_image_with_fallback(gsr_pipewire_v if(self->no_modifiers_fallback) { image = gsr_pipewire_video_create_egl_image(self, fds, offsets, pitches, modifiers, false); } else { - image = gsr_pipewire_video_create_egl_image(self, fds, offsets, pitches, modifiers, self->format.info.raw.modifier != 0); + image = gsr_pipewire_video_create_egl_image(self, fds, offsets, pitches, modifiers, true); if(!image) { - if(self->renegotiated) { + if(self->renegotiated || self->format.info.raw.modifier == DRM_FORMAT_MOD_INVALID) { fprintf(stderr, "gsr error: gsr_pipewire_video_create_egl_image_with_fallback: failed to create egl image with modifiers, trying without modifiers\n"); self->no_modifiers_fallback = true; image = gsr_pipewire_video_create_egl_image(self, fds, offsets, pitches, modifiers, false);