aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c112
1 files changed, 42 insertions, 70 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index f936b2a8..8711a248 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -232,6 +232,23 @@ static void output_configure_scene(struct sway_output *output,
232 } 232 }
233} 233}
234 234
235static bool output_can_tear(struct sway_output *output) {
236 struct sway_workspace *workspace = output->current.active_workspace;
237 if (!workspace) {
238 return false;
239 }
240
241 struct sway_container *fullscreen_con = root->fullscreen_global;
242 if (!fullscreen_con) {
243 fullscreen_con = workspace->current.fullscreen;
244 }
245 if (fullscreen_con && fullscreen_con->view) {
246 return (output->allow_tearing && view_can_tear(fullscreen_con->view));
247 }
248
249 return false;
250}
251
235static int output_repaint_timer_handler(void *data) { 252static int output_repaint_timer_handler(void *data) {
236 struct sway_output *output = data; 253 struct sway_output *output = data;
237 254
@@ -247,25 +264,24 @@ static int output_repaint_timer_handler(void *data) {
247 .color_transform = output->color_transform, 264 .color_transform = output->color_transform,
248 }; 265 };
249 266
267 struct wlr_scene_output *scene_output = output->scene_output;
268 if (!wlr_scene_output_needs_frame(scene_output)) {
269 return 0;
270 }
271
250 struct wlr_output_state pending; 272 struct wlr_output_state pending;
251 wlr_output_state_init(&pending); 273 wlr_output_state_init(&pending);
252 if (!wlr_scene_output_build_state(output->scene_output, &pending, &opts)) { 274 if (!wlr_scene_output_build_state(output->scene_output, &pending, &opts)) {
253 return 0; 275 return 0;
254 } 276 }
255 277
256 if (output->gamma_lut_changed) { 278 if (output_can_tear(output)) {
257 output->gamma_lut_changed = false; 279 pending.tearing_page_flip = true;
258 struct wlr_gamma_control_v1 *gamma_control =
259 wlr_gamma_control_manager_v1_get_control(
260 server.gamma_control_manager_v1, output->wlr_output);
261 if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
262 wlr_output_state_finish(&pending);
263 return 0;
264 }
265 280
266 if (!wlr_output_test_state(output->wlr_output, &pending)) { 281 if (!wlr_output_test_state(output->wlr_output, &pending)) {
267 wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); 282 sway_log(SWAY_DEBUG, "Output test failed on '%s', retrying without tearing page-flip",
268 wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL); 283 output->wlr_output->name);
284 pending.tearing_page_flip = false;
269 } 285 }
270 } 286 }
271 287
@@ -340,7 +356,7 @@ static void handle_frame(struct wl_listener *listener, void *user_data) {
340 wlr_scene_output_for_each_buffer(output->scene_output, send_frame_done_iterator, &data); 356 wlr_scene_output_for_each_buffer(output->scene_output, send_frame_done_iterator, &data);
341} 357}
342 358
343static void update_output_manager_config(struct sway_server *server) { 359void update_output_manager_config(struct sway_server *server) {
344 struct wlr_output_configuration_v1 *config = 360 struct wlr_output_configuration_v1 *config =
345 wlr_output_configuration_v1_create(); 361 wlr_output_configuration_v1_create();
346 362
@@ -371,9 +387,6 @@ static int timer_modeset_handle(void *data) {
371 server->delayed_modeset = NULL; 387 server->delayed_modeset = NULL;
372 388
373 apply_all_output_configs(); 389 apply_all_output_configs();
374 transaction_commit_dirty();
375 update_output_manager_config(server);
376
377 return 0; 390 return 0;
378} 391}
379 392
@@ -398,7 +411,6 @@ static void begin_destroy(struct sway_output *output) {
398 411
399 wl_list_remove(&output->layout_destroy.link); 412 wl_list_remove(&output->layout_destroy.link);
400 wl_list_remove(&output->destroy.link); 413 wl_list_remove(&output->destroy.link);
401 wl_list_remove(&output->commit.link);
402 wl_list_remove(&output->present.link); 414 wl_list_remove(&output->present.link);
403 wl_list_remove(&output->frame.link); 415 wl_list_remove(&output->frame.link);
404 wl_list_remove(&output->request_state.link); 416 wl_list_remove(&output->request_state.link);
@@ -421,31 +433,6 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
421 begin_destroy(output); 433 begin_destroy(output);
422} 434}
423 435
424static void handle_commit(struct wl_listener *listener, void *data) {
425 struct sway_output *output = wl_container_of(listener, output, commit);
426 struct wlr_output_event_commit *event = data;
427
428 if (!output->enabled) {
429 return;
430 }
431
432 if (event->state->committed & (
433 WLR_OUTPUT_STATE_MODE |
434 WLR_OUTPUT_STATE_TRANSFORM |
435 WLR_OUTPUT_STATE_SCALE)) {
436 arrange_layers(output);
437 arrange_output(output);
438 transaction_commit_dirty();
439
440 update_output_manager_config(output->server);
441 }
442
443 // Next time the output is enabled, try to re-apply the gamma LUT
444 if ((event->state->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) {
445 output->gamma_lut_changed = true;
446 }
447}
448
449static void handle_present(struct wl_listener *listener, void *data) { 436static void handle_present(struct wl_listener *listener, void *data) {
450 struct sway_output *output = wl_container_of(listener, output, present); 437 struct sway_output *output = wl_container_of(listener, output, present);
451 struct wlr_output_event_present *output_event = data; 438 struct wlr_output_event_present *output_event = data;
@@ -454,7 +441,7 @@ static void handle_present(struct wl_listener *listener, void *data) {
454 return; 441 return;
455 } 442 }
456 443
457 output->last_presentation = *output_event->when; 444 output->last_presentation = output_event->when;
458 output->refresh_nsec = output_event->refresh; 445 output->refresh_nsec = output_event->refresh;
459} 446}
460 447
@@ -462,7 +449,20 @@ static void handle_request_state(struct wl_listener *listener, void *data) {
462 struct sway_output *output = 449 struct sway_output *output =
463 wl_container_of(listener, output, request_state); 450 wl_container_of(listener, output, request_state);
464 const struct wlr_output_event_request_state *event = data; 451 const struct wlr_output_event_request_state *event = data;
452
453 uint32_t committed = event->state->committed;
465 wlr_output_commit_state(output->wlr_output, event->state); 454 wlr_output_commit_state(output->wlr_output, event->state);
455
456 if (committed & (
457 WLR_OUTPUT_STATE_MODE |
458 WLR_OUTPUT_STATE_TRANSFORM |
459 WLR_OUTPUT_STATE_SCALE)) {
460 arrange_layers(output);
461 arrange_output(output);
462 transaction_commit_dirty();
463
464 update_output_manager_config(output->server);
465 }
466} 466}
467 467
468static unsigned int last_headless_num = 0; 468static unsigned int last_headless_num = 0;
@@ -526,8 +526,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
526 output->layout_destroy.notify = handle_layout_destroy; 526 output->layout_destroy.notify = handle_layout_destroy;
527 wl_signal_add(&wlr_output->events.destroy, &output->destroy); 527 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
528 output->destroy.notify = handle_destroy; 528 output->destroy.notify = handle_destroy;
529 wl_signal_add(&wlr_output->events.commit, &output->commit);
530 output->commit.notify = handle_commit;
531 wl_signal_add(&wlr_output->events.present, &output->present); 529 wl_signal_add(&wlr_output->events.present, &output->present);
532 output->present.notify = handle_present; 530 output->present.notify = handle_present;
533 wl_signal_add(&wlr_output->events.frame, &output->frame); 531 wl_signal_add(&wlr_output->events.frame, &output->frame);
@@ -545,28 +543,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
545 request_modeset(server); 543 request_modeset(server);
546} 544}
547 545
548void handle_output_layout_change(struct wl_listener *listener,
549 void *data) {
550 struct sway_server *server =
551 wl_container_of(listener, server, output_layout_change);
552 update_output_manager_config(server);
553}
554
555void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
556 struct sway_server *server =
557 wl_container_of(listener, server, gamma_control_set_gamma);
558 const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
559
560 struct sway_output *output = event->output->data;
561
562 if(!output) {
563 return;
564 }
565
566 output->gamma_lut_changed = true;
567 wlr_output_schedule_frame(output->wlr_output);
568}
569
570static struct output_config *output_config_for_config_head( 546static struct output_config *output_config_for_config_head(
571 struct wlr_output_configuration_head_v1 *config_head, 547 struct wlr_output_configuration_head_v1 *config_head,
572 struct sway_output *output) { 548 struct sway_output *output) {
@@ -657,10 +633,6 @@ static void output_manager_apply(struct sway_server *server,
657 wlr_output_configuration_v1_send_failed(config); 633 wlr_output_configuration_v1_send_failed(config);
658 } 634 }
659 wlr_output_configuration_v1_destroy(config); 635 wlr_output_configuration_v1_destroy(config);
660
661 if (!test_only) {
662 update_output_manager_config(server);
663 }
664} 636}
665 637
666void handle_output_manager_apply(struct wl_listener *listener, void *data) { 638void handle_output_manager_apply(struct wl_listener *listener, void *data) {