From 889c5ed5ff120053c8a6d96e08e81c2a5f01c523 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 15 Nov 2023 18:38:12 -0500 Subject: [PATCH] wlr_scene: Update outputs when output scale/transform changes We want to call the outputs updated signal when an output scale or transform changes. Otherwise helpers like the scene surface helpers will not be notified of scale changes and not pass them to clients. --- types/scene/wlr_scene.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 89c9b679..cd3094be 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -333,7 +333,8 @@ static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *dam } static void update_node_update_outputs(struct wlr_scene_node *node, - struct wl_list *outputs, struct wlr_scene_output *ignore) { + struct wl_list *outputs, struct wlr_scene_output *ignore, + struct wlr_scene_output *force) { if (node->type != WLR_SCENE_NODE_BUFFER) { return; } @@ -413,8 +414,8 @@ static void update_node_update_outputs(struct wlr_scene_node *node, // output assert(!scene_buffer->active_outputs || scene_buffer->primary_output); - // if no outputs changes intersection status, skip calling outputs_update - if (old_active == active_outputs) { + // Skip output update event if nothing was updated + if (old_active == active_outputs && (!force || ((1ull << force->index) & ~active_outputs))) { return; } @@ -457,7 +458,7 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node, pixman_region32_fini(&opaque); } - update_node_update_outputs(node, data->outputs, NULL); + update_node_update_outputs(node, data->outputs, NULL, NULL); return false; } @@ -1240,25 +1241,27 @@ static const struct wlr_addon_interface output_addon_impl = { }; static void scene_node_output_update(struct wlr_scene_node *node, - struct wl_list *outputs, struct wlr_scene_output *ignore) { + struct wl_list *outputs, struct wlr_scene_output *ignore, + struct wlr_scene_output *force) { if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node); struct wlr_scene_node *child; wl_list_for_each(child, &scene_tree->children, link) { - scene_node_output_update(child, outputs, ignore); + scene_node_output_update(child, outputs, ignore, force); } return; } - update_node_update_outputs(node, outputs, ignore); + update_node_update_outputs(node, outputs, ignore, force); } -static void scene_output_update_geometry(struct wlr_scene_output *scene_output) { +static void scene_output_update_geometry(struct wlr_scene_output *scene_output, + bool force_update) { wlr_damage_ring_add_whole(&scene_output->damage_ring); wlr_output_schedule_frame(scene_output->output); scene_node_output_update(&scene_output->scene->tree.node, - &scene_output->scene->outputs, NULL); + &scene_output->scene->outputs, NULL, force_update ? scene_output : NULL); } static void scene_output_handle_commit(struct wl_listener *listener, void *data) { @@ -1267,11 +1270,13 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data) struct wlr_output_event_commit *event = data; const struct wlr_output_state *state = event->state; - if (state->committed & (WLR_OUTPUT_STATE_MODE | - WLR_OUTPUT_STATE_TRANSFORM | - WLR_OUTPUT_STATE_SCALE | + bool force_update = state->committed & ( + WLR_OUTPUT_STATE_TRANSFORM | + WLR_OUTPUT_STATE_SCALE); + + if (force_update || state->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_ENABLED)) { - scene_output_update_geometry(scene_output); + scene_output_update_geometry(scene_output, force_update); } } @@ -1332,7 +1337,7 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, scene_output->output_needs_frame.notify = scene_output_handle_needs_frame; wl_signal_add(&output->events.needs_frame, &scene_output->output_needs_frame); - scene_output_update_geometry(scene_output); + scene_output_update_geometry(scene_output, false); return scene_output; } @@ -1351,7 +1356,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wl_signal_emit_mutable(&scene_output->events.destroy, NULL); scene_node_output_update(&scene_output->scene->tree.node, - &scene_output->scene->outputs, scene_output); + &scene_output->scene->outputs, scene_output, NULL); struct highlight_region *damage, *tmp_damage; wl_list_for_each_safe(damage, tmp_damage, &scene_output->damage_highlight_regions, link) { @@ -1390,7 +1395,7 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, scene_output->x = lx; scene_output->y = ly; - scene_output_update_geometry(scene_output); + scene_output_update_geometry(scene_output, false); } static bool scene_node_invisible(struct wlr_scene_node *node) {