diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 112 |
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 | ||
235 | static 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 | |||
235 | static int output_repaint_timer_handler(void *data) { | 252 | static 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 | ||
343 | static void update_output_manager_config(struct sway_server *server) { | 359 | void 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 | ||
424 | static 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 | |||
449 | static void handle_present(struct wl_listener *listener, void *data) { | 436 | static 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 | ||
468 | static unsigned int last_headless_num = 0; | 468 | static 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 | ||
548 | void 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 | |||
555 | void 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 | |||
570 | static struct output_config *output_config_for_config_head( | 546 | static 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 | ||
666 | void handle_output_manager_apply(struct wl_listener *listener, void *data) { | 638 | void handle_output_manager_apply(struct wl_listener *listener, void *data) { |