From b9c4472c505eea8bcd62a18240e9b8ac639798bd Mon Sep 17 00:00:00 2001 From: columbarius Date: Sun, 24 Apr 2022 14:38:44 +0200 Subject: [PATCH] screencast: stop assuming that allocation with implicit modifier works It has shown that the assumption: "Allocation with implicit modifier will always be available" doesn't hold true in all cases. Thus if allocation of any dmabuf fails we mark the session to avoid dmabufs, thus falling back to shm transport. --- include/screencast_common.h | 1 + src/screencast/pipewire_screencast.c | 19 ++++++++++--------- src/screencast/screencast.c | 1 + 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/screencast_common.h b/include/screencast_common.h index 8e83b6f..d180084 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -126,6 +126,7 @@ struct xdpw_screencast_instance { struct xdpw_frame current_frame; enum xdpw_frame_state frame_state; struct wl_list buffer_list; + bool avoid_dmabufs; // pipewire struct pw_stream *stream; diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index cef3b92..9bebc4c 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -94,11 +94,7 @@ static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_fo SPA_POD_CHOICE_ENUM_Id(3, format, format, format_without_alpha), 0); } /* modifiers */ - if (modifier_count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { - // we only support implicit modifiers, use shortpath to skip fixation phase - spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY); - spa_pod_builder_long(b, modifiers[0]); - } else if (modifier_count > 0) { + if (modifier_count > 0) { // build an enumeration of modifiers spa_pod_builder_prop(b, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE); spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_Enum, 0); @@ -131,7 +127,7 @@ static uint32_t build_formats(struct spa_pod_builder *b, struct xdpw_screencast_ uint32_t modifier_count = 1; uint64_t modifier = DRM_FORMAT_MOD_INVALID; - if (cast->ctx->gbm) { + if (cast->ctx->gbm && !cast->avoid_dmabufs) { param_count = 2; params[0] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[DMABUF].format), cast->screencopy_frame_info[DMABUF].width, cast->screencopy_frame_info[DMABUF].height, cast->framerate, @@ -208,6 +204,7 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, modifiers++; uint32_t flags = GBM_BO_USE_RENDERING; uint64_t modifier; + uint32_t n_params; struct gbm_bo *bo = gbm_bo_create_with_modifiers2(cast->ctx->gbm, cast->screencopy_frame_info[cast->buffer_type].width, cast->screencopy_frame_info[cast->buffer_type].height, @@ -239,14 +236,18 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id, } } - logprint(ERROR, "pipewire: unable to allocate a dmabuf"); - abort(); + logprint(WARN, "pipewire: unable to allocate a dmabuf. Falling back to shm"); + cast->avoid_dmabufs = true; + + n_params = build_formats(&b, cast, ¶ms[0]); + pw_stream_update_params(stream, params, n_params); + return; fixate_format: params[0] = fixate_format(&b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format), cast->screencopy_frame_info[cast->buffer_type].width, cast->screencopy_frame_info[cast->buffer_type].height, cast->framerate, &modifier); - uint32_t n_params = build_formats(&b, cast, ¶ms[1]); + n_params = build_formats(&b, cast, ¶ms[1]); n_params++; pw_stream_update_params(stream, params, n_params); diff --git a/src/screencast/screencast.c b/src/screencast/screencast.c index 888976e..466216d 100644 --- a/src/screencast/screencast.c +++ b/src/screencast/screencast.c @@ -70,6 +70,7 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx, cast->with_cursor = with_cursor; cast->refcount = 1; cast->node_id = SPA_ID_INVALID; + cast->avoid_dmabufs = false; wl_list_init(&cast->buffer_list); logprint(INFO, "xdpw: screencast instance %p has %d references", cast, cast->refcount); wl_list_insert(&ctx->screencast_instances, &cast->link);