summaryrefslogtreecommitdiff
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c155
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);