diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 155 |
1 files changed, 107 insertions, 48 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index b6d19dd6..182ca428 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -10,11 +10,10 @@ #include <wlr/types/wlr_buffer.h> #include <wlr/types/wlr_drm_lease_v1.h> #include <wlr/types/wlr_matrix.h> -#include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output.h> #include <wlr/types/wlr_presentation_time.h> -#include <wlr/types/wlr_surface.h> +#include <wlr/types/wlr_compositor.h> #include <wlr/util/region.h> #include "config.h" #include "log.h" @@ -276,6 +275,25 @@ static void for_each_surface_container_iterator(struct sway_container *con, static void output_for_each_surface(struct sway_output *output, sway_surface_iterator_func_t iterator, void *user_data) { + if (server.session_lock.locked) { + if (server.session_lock.lock == NULL) { + return; + } + struct wlr_session_lock_surface_v1 *lock_surface; + wl_list_for_each(lock_surface, &server.session_lock.lock->surfaces, link) { + if (lock_surface->output != output->wlr_output) { + continue; + } + if (!lock_surface->mapped) { + continue; + } + + output_surface_for_each_surface(output, lock_surface->surface, + 0.0, 0.0, iterator, user_data); + } + return; + } + if (output_has_opaque_overlay_layer_surface(output)) { goto overlay; } @@ -435,6 +453,10 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return false; } + if (server.session_lock.locked) { + return false; + } + if (!wl_list_empty(&view->saved_buffers)) { return false; } @@ -533,31 +555,43 @@ static int output_repaint_timer_handler(void *data) { } } - bool needs_frame; + int buffer_age; + if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { + return 0; + } + pixman_region32_t damage; pixman_region32_init(&damage); - if (!wlr_output_damage_attach_render(output->damage, - &needs_frame, &damage)) { + wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); + if (!output->wlr_output->needs_frame && + !pixman_region32_not_empty(&output->damage_ring.current)) { + pixman_region32_fini(&damage); + wlr_output_rollback(output->wlr_output); return 0; } - if (needs_frame) { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); - output_render(output, &now, &damage); - } else { - wlr_output_rollback(output->wlr_output); - } + output_render(output, &now, &damage); pixman_region32_fini(&damage); return 0; } -static void damage_handle_frame(struct wl_listener *listener, void *user_data) { +static void handle_damage(struct wl_listener *listener, void *user_data) { + struct sway_output *output = + wl_container_of(listener, output, damage); + struct wlr_output_event_damage *event = user_data; + if (wlr_damage_ring_add(&output->damage_ring, event->damage)) { + wlr_output_schedule_frame(output->wlr_output); + } +} + +static void handle_frame(struct wl_listener *listener, void *user_data) { struct sway_output *output = - wl_container_of(listener, output, damage_frame); + wl_container_of(listener, output, frame); if (!output->enabled || !output->wlr_output->enabled) { return; } @@ -620,11 +654,18 @@ static void damage_handle_frame(struct wl_listener *listener, void *user_data) { send_frame_done(output, &data); } +static void handle_needs_frame(struct wl_listener *listener, void *user_data) { + struct sway_output *output = + wl_container_of(listener, output, needs_frame); + wlr_output_schedule_frame(output->wlr_output); +} + void output_damage_whole(struct sway_output *output) { // The output can exist with no wlr_output if it's just been disconnected // and the transaction to evacuate it has't completed yet. - if (output && output->wlr_output && output->damage) { - wlr_output_damage_add_whole(output->damage); + if (output != NULL && output->wlr_output != NULL) { + wlr_damage_ring_add_whole(&output->damage_ring); + wlr_output_schedule_frame(output->wlr_output); } } @@ -648,11 +689,15 @@ static void damage_surface_iterator(struct sway_output *output, ceil(output->wlr_output->scale) - surface->current.scale); } pixman_region32_translate(&damage, box.x, box.y); - wlr_output_damage_add(output->damage, &damage); + if (wlr_damage_ring_add(&output->damage_ring, &damage)) { + wlr_output_schedule_frame(output->wlr_output); + } pixman_region32_fini(&damage); if (whole) { - wlr_output_damage_add_box(output->damage, &box); + if (wlr_damage_ring_add_box(&output->damage_ring, &box)) { + wlr_output_schedule_frame(output->wlr_output); + } } if (!wl_list_empty(&surface->current.frame_callback_list)) { @@ -682,7 +727,9 @@ void output_damage_box(struct sway_output *output, struct wlr_box *_box) { box.x -= output->lx; box.y -= output->ly; scale_box(&box, output->wlr_output->scale); - wlr_output_damage_add_box(output->damage, &box); + if (wlr_damage_ring_add_box(&output->damage_ring, &box)) { + wlr_output_schedule_frame(output->wlr_output); + } } static void damage_child_views_iterator(struct sway_container *con, @@ -706,7 +753,9 @@ void output_damage_whole_container(struct sway_output *output, .height = con->current.height + 2, }; scale_box(&box, output->wlr_output->scale); - wlr_output_damage_add_box(output->damage, &box); + if (wlr_damage_ring_add_box(&output->damage_ring, &box)) { + wlr_output_schedule_frame(output->wlr_output); + } // Damage subsurfaces as well, which may extend outside the box if (con->view) { damage_child_views_iterator(con, output); @@ -715,20 +764,6 @@ void output_damage_whole_container(struct sway_output *output, } } -static void damage_handle_destroy(struct wl_listener *listener, void *data) { - struct sway_output *output = - wl_container_of(listener, output, damage_destroy); - if (!output->enabled) { - return; - } - output_disable(output); - - wl_list_remove(&output->damage_destroy.link); - wl_list_remove(&output->damage_frame.link); - - transaction_commit_dirty(); -} - static void update_output_manager_config(struct sway_server *server) { struct wlr_output_configuration_v1 *config = wlr_output_configuration_v1_create(); @@ -740,14 +775,15 @@ static void update_output_manager_config(struct sway_server *server) { } struct wlr_output_configuration_head_v1 *config_head = wlr_output_configuration_head_v1_create(config, output->wlr_output); - struct wlr_box *output_box = wlr_output_layout_get_box( - root->output_layout, output->wlr_output); - // We mark the output enabled even if it is switched off by DPMS + struct wlr_box output_box; + wlr_output_layout_get_box(root->output_layout, + output->wlr_output, &output_box); + // We mark the output enabled when it's switched off but not disabled config_head->state.enabled = output->current_mode != NULL && output->enabled; config_head->state.mode = output->current_mode; - if (output_box) { - config_head->state.x = output_box->x; - config_head->state.y = output_box->y; + if (!wlr_box_empty(&output_box)) { + config_head->state.x = output_box.x; + config_head->state.y = output_box.y; } } @@ -757,18 +793,24 @@ static void update_output_manager_config(struct sway_server *server) { static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, destroy); struct sway_server *server = output->server; - output_begin_destroy(output); if (output->enabled) { output_disable(output); } + output_begin_destroy(output); + wl_list_remove(&output->link); wl_list_remove(&output->destroy.link); wl_list_remove(&output->commit.link); wl_list_remove(&output->mode.link); wl_list_remove(&output->present.link); + wl_list_remove(&output->damage.link); + wl_list_remove(&output->frame.link); + wl_list_remove(&output->needs_frame.link); + + wlr_damage_ring_finish(&output->damage_ring); output->wlr_output->data = NULL; output->wlr_output = NULL; @@ -796,10 +838,16 @@ static void handle_mode(struct wl_listener *listener, void *data) { if (!output->enabled) { return; } + arrange_layers(output); arrange_output(output); transaction_commit_dirty(); + int width, height; + wlr_output_transformed_resolution(output->wlr_output, &width, &height); + wlr_damage_ring_set_bounds(&output->damage_ring, width, height); + wlr_output_schedule_frame(output->wlr_output); + update_output_manager_config(output->server); } @@ -827,6 +875,13 @@ static void handle_commit(struct wl_listener *listener, void *data) { update_output_manager_config(output->server); } + + if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM)) { + int width, height; + wlr_output_transformed_resolution(output->wlr_output, &width, &height); + wlr_damage_ring_set_bounds(&output->damage_ring, width, height); + wlr_output_schedule_frame(output->wlr_output); + } } static void handle_present(struct wl_listener *listener, void *data) { @@ -862,10 +917,12 @@ void handle_new_output(struct wl_listener *listener, void *data) { if (wlr_output->non_desktop) { sway_log(SWAY_DEBUG, "Not configuring non-desktop output"); + struct sway_output_non_desktop *non_desktop = output_non_desktop_create(wlr_output); if (server->drm_lease_manager) { wlr_drm_lease_v1_manager_offer_output(server->drm_lease_manager, wlr_output); } + list_add(root->non_desktop_outputs, non_desktop); return; } @@ -880,7 +937,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { return; } output->server = server; - output->damage = wlr_output_damage_create(wlr_output); + wlr_damage_ring_init(&output->damage_ring); wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_destroy; @@ -890,10 +947,12 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->mode.notify = handle_mode; wl_signal_add(&wlr_output->events.present, &output->present); output->present.notify = handle_present; - wl_signal_add(&output->damage->events.frame, &output->damage_frame); - output->damage_frame.notify = damage_handle_frame; - wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); - output->damage_destroy.notify = damage_handle_destroy; + wl_signal_add(&wlr_output->events.damage, &output->damage); + output->damage.notify = handle_damage; + wl_signal_add(&wlr_output->events.frame, &output->frame); + output->frame.notify = handle_frame; + wl_signal_add(&wlr_output->events.needs_frame, &output->needs_frame); + output->needs_frame.notify = handle_needs_frame; output->repaint_timer = wl_event_loop_add_timer(server->wl_event_loop, output_repaint_timer_handler, output); @@ -1007,10 +1066,10 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener, struct output_config *oc = new_output_config(output->wlr_output->name); switch (event->mode) { case ZWLR_OUTPUT_POWER_V1_MODE_OFF: - oc->dpms_state = DPMS_OFF; + oc->power = 0; break; case ZWLR_OUTPUT_POWER_V1_MODE_ON: - oc->dpms_state = DPMS_ON; + oc->power = 1; break; } oc = store_output_config(oc); |