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