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.
This commit is contained in:
columbarius 2021-06-16 18:59:34 +02:00
parent fc85f6738b
commit 78efdff460

View file

@ -101,22 +101,6 @@ static struct wl_buffer *create_shm_buffer(struct xdpw_screencast_instance *cast
return buffer; 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, static void wlr_frame_linux_dmabuf(void *data,
struct zwlr_screencopy_frame_v1 *frame, struct zwlr_screencopy_frame_v1 *frame,
uint32_t format, uint32_t width, uint32_t height) { 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; struct xdpw_screencast_instance *cast = data;
logprint(TRACE, "wlroots: buffer_done event handler"); logprint(TRACE, "wlroots: buffer_done event handler");
if (cast->pwr_stream_state) {
if (!cast->quit && !cast->err && cast->pwr_stream_state) {
xdpw_pwr_dequeue_buffer(cast); 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); 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"); logprint(TRACE, "wlroots: buffer event handler");
cast->wlr_frame = frame; cast->wlr_frame = frame;
if (cast->screencopy_frame.width != width ||
cast->screencopy_frame.height != height || cast->screencopy_frame.width = width;
cast->screencopy_frame.stride != stride || cast->screencopy_frame.height = height;
cast->screencopy_frame.format != format) { cast->screencopy_frame.stride = stride;
logprint(TRACE, "wlroots: buffer properties changed"); cast->screencopy_frame.size = stride * height;
wlr_frame_buffer_chparam(cast, format, width, height, stride); cast->screencopy_frame.format = format;
}
if (cast->screencopy_frame.buffer == NULL) { if (cast->screencopy_frame.buffer == NULL) {
logprint(DEBUG, "wlroots: create shm buffer"); logprint(DEBUG, "wlroots: create shm buffer");