From 78efdff4602ef99201d9dd11ed6b107226188260 Mon Sep 17 00:00:00 2001 From: columbarius Date: Wed, 16 Jun 2021 18:59:34 +0200 Subject: [PATCH] screencast: implement buffer property checks wrt. xdpw_frame and xdpw_screencopy_frame Since we gather the information of the currently used buffer on importing it, we can check if the imported and the announce buffer by wlroots are compatible. Also the comparison between the announced buffer properties and the format used by the pipewire stream was moved to wlr_frame_buffer_done. This lets us implement all checks in the same callback and makes it easier to extend those checks for future dmabuf sharing. --- src/screencast/wlr_screencast.c | 64 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 349a52d..b56e8a9 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -101,22 +101,6 @@ static struct wl_buffer *create_shm_buffer(struct xdpw_screencast_instance *cast return buffer; } -static void wlr_frame_buffer_chparam(struct xdpw_screencast_instance *cast, - uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { - logprint(DEBUG, "wlroots: reset buffer"); - cast->screencopy_frame.width = width; - cast->screencopy_frame.height = height; - cast->screencopy_frame.stride = stride; - cast->screencopy_frame.size = stride * height; - cast->screencopy_frame.format = format; - wlr_frame_buffer_destroy(cast); - - if (cast->pwr_stream_state) { - logprint(DEBUG, "wlroots: request pipewire param change"); - pwr_update_stream_param(cast); - } -} - static void wlr_frame_linux_dmabuf(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height) { @@ -128,13 +112,38 @@ static void wlr_frame_buffer_done(void *data, struct xdpw_screencast_instance *cast = data; logprint(TRACE, "wlroots: buffer_done event handler"); - - if (!cast->quit && !cast->err && cast->pwr_stream_state) { + if (cast->pwr_stream_state) { xdpw_pwr_dequeue_buffer(cast); - if (!cast->current_frame.current_pw_buffer) { - xdpw_wlr_frame_free(cast); - return; + } + + if (!cast->current_frame.current_pw_buffer) { + logprint(WARN, "wlroots: failed to dequeue buffer"); + xdpw_wlr_frame_free(cast); + return; + } + + // Check if announced screencopy information is compatible with pipewire meta + if ((cast->pwr_format.format != xdpw_format_pw_from_wl_shm(cast->screencopy_frame.format) && + cast->pwr_format.format != xdpw_format_pw_strip_alpha(xdpw_format_pw_from_wl_shm(cast->screencopy_frame.format))) || + cast->pwr_format.size.width != cast->screencopy_frame.width || + cast->pwr_format.size.height != cast->screencopy_frame.height) { + logprint(DEBUG, "wlroots: pipewire and wlroots metadata are incompatible. Renegotiate stream"); + + xdpw_pwr_enqueue_buffer(cast); + if (cast->pwr_stream_state) { + pwr_update_stream_param(cast); } + xdpw_wlr_frame_free(cast); + return; + } + + // Check if dequeued buffer is compatible with announced buffer + if (cast->current_frame.size != cast->screencopy_frame.size || + cast->current_frame.stride != cast->screencopy_frame.stride) { + logprint(DEBUG, "wlroots: pipewire buffer has wrong dimensions"); + xdpw_pwr_enqueue_buffer(cast); + xdpw_wlr_frame_free(cast); + return; } zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->screencopy_frame.buffer); @@ -149,13 +158,12 @@ static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, logprint(TRACE, "wlroots: buffer event handler"); cast->wlr_frame = frame; - if (cast->screencopy_frame.width != width || - cast->screencopy_frame.height != height || - cast->screencopy_frame.stride != stride || - cast->screencopy_frame.format != format) { - logprint(TRACE, "wlroots: buffer properties changed"); - wlr_frame_buffer_chparam(cast, format, width, height, stride); - } + + cast->screencopy_frame.width = width; + cast->screencopy_frame.height = height; + cast->screencopy_frame.stride = stride; + cast->screencopy_frame.size = stride * height; + cast->screencopy_frame.format = format; if (cast->screencopy_frame.buffer == NULL) { logprint(DEBUG, "wlroots: create shm buffer");