From 50d92f9d6f1590858c14f1b8d70d83ccc87993a3 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 30 Aug 2024 07:46:06 -0500 Subject: [PATCH] libweston: Fix crash with mirror-of Since c4eb15d453f40fd71d52099dc899df18ee2ce4b8 we keep a copy of native mode parameters, however we forgot to initialize the native mode parameters in some situations, which breaks the output mirroring code when it sees uninitialized data. Fixes c4eb15d453f40fd71d52099dc899df18ee2ce4b8 Fixes #949 Signed-off-by: Derek Foreman --- frontend/main.c | 3 ++ libweston/backend-drm/modes.c | 2 +- libweston/backend-pipewire/pipewire.c | 7 +++-- libweston/backend-x11/x11.c | 2 +- libweston/compositor.c | 40 +++++++++++++++++++++------ libweston/libweston-internal.h | 4 +++ 6 files changed, 45 insertions(+), 13 deletions(-) diff --git a/frontend/main.c b/frontend/main.c index 3f02d1dd..c27c011d 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -2540,6 +2540,9 @@ wet_output_compute_output_from_mirror(struct weston_output *output, struct weston_mode *mode, int *scale) { + assert(output->native_mode_copy.width); + assert(output->native_mode_copy.height); + mode->width = output->native_mode_copy.width / mirror->current_scale; diff --git a/libweston/backend-drm/modes.c b/libweston/backend-drm/modes.c index 12891d6b..aecd4069 100644 --- a/libweston/backend-drm/modes.c +++ b/libweston/backend-drm/modes.c @@ -912,7 +912,7 @@ drm_output_set_mode(struct weston_output *base, output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT; /* Set native_ fields, so weston_output_mode_switch_to_native() works */ - output->base.native_mode = output->base.current_mode; + weston_output_copy_native_mode(&output->base, output->base.current_mode); output->base.native_scale = output->base.current_scale; return 0; diff --git a/libweston/backend-pipewire/pipewire.c b/libweston/backend-pipewire/pipewire.c index 2643800c..56bf591e 100644 --- a/libweston/backend-pipewire/pipewire.c +++ b/libweston/backend-pipewire/pipewire.c @@ -1129,7 +1129,8 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode base->current_mode->flags &= ~WL_OUTPUT_MODE_CURRENT; - base->current_mode = base->native_mode = local_mode; + base->current_mode = local_mode; + weston_output_copy_native_mode(base, local_mode); base->current_mode->flags |= WL_OUTPUT_MODE_CURRENT; fb_size.width = target_mode->width; @@ -1172,8 +1173,8 @@ pipewire_output_set_size(struct weston_output *base, int width, int height) current_mode = pipewire_ensure_matching_mode(&output->base, &init_mode); current_mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; - output->base.current_mode = output->base.native_mode = current_mode; - + output->base.current_mode = current_mode; + weston_output_copy_native_mode(base, current_mode); output->base.start_repaint_loop = pipewire_output_start_repaint_loop; output->base.repaint = pipewire_output_repaint; output->base.assign_planes = NULL; diff --git a/libweston/backend-x11/x11.c b/libweston/backend-x11/x11.c index 48d3ab99..8c87d9ed 100644 --- a/libweston/backend-x11/x11.c +++ b/libweston/backend-x11/x11.c @@ -1182,7 +1182,7 @@ x11_output_set_size(struct weston_output *base, int width, int height) wl_list_insert(&output->base.mode_list, &output->mode.link); output->base.current_mode = &output->mode; - output->base.native_mode = &output->native; + weston_output_copy_native_mode(&output->base, &output->mode); output->base.native_scale = output->base.current_scale; return 0; diff --git a/libweston/compositor.c b/libweston/compositor.c index ee1fad3b..3d0d06a1 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -525,6 +525,36 @@ static void weston_compositor_reflow_outputs(struct weston_compositor *compositor, struct weston_output *resized_output, int delta_width); +/** Set up the native mode for an output + * + * \param output The weston_output object + * \param mode The new native mode + * + * Our mode setting code does some ugly tricks, and will + * sometimes save pointers to ephemeral structures for + * comparison later. + * + * To work around this fragility, we copy the contents of + * the native mode at set time. + * + * This function will be removed when we fix the mode set + * code. + * + * \ingroup output + * \internal + */ +WL_EXPORT void +weston_output_copy_native_mode(struct weston_output *output, + struct weston_mode *mode) +{ + output->native_mode = mode; + output->native_mode_copy.width = mode->width; + output->native_mode_copy.height = mode->height; + output->native_mode_copy.flags = mode->flags; + output->native_mode_copy.aspect_ratio = mode->aspect_ratio; + output->native_mode_copy.refresh = mode->refresh; +} + /** * \ingroup output */ @@ -552,15 +582,9 @@ weston_output_mode_set_native(struct weston_output *output, } old_width = output->width; - output->native_mode = mode; + weston_output_copy_native_mode(output, mode); output->native_scale = scale; - output->native_mode_copy.width = mode->width; - output->native_mode_copy.height = mode->height; - output->native_mode_copy.flags = mode->flags; - output->native_mode_copy.aspect_ratio = mode->aspect_ratio; - output->native_mode_copy.refresh = mode->refresh; - weston_mode_switch_finish(output, mode_changed, scale_changed); if (mode_changed || scale_changed) { @@ -8053,7 +8077,7 @@ weston_output_set_single_mode(struct weston_output *output, wl_list_insert(&output->mode_list, &mode->link); out: output->current_mode = mode; - output->native_mode = mode; + weston_output_copy_native_mode(output, mode); if (local) { wl_list_remove(&local->link); diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index ff99a52c..0cdb9e2d 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -656,4 +656,8 @@ convert_size_by_transform_scale(int32_t *width_out, int32_t *height_out, bool weston_authenticate_user(const char *username, const char *password); +void +weston_output_copy_native_mode(struct weston_output *output, + struct weston_mode *mode); + #endif