diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 111 |
1 files changed, 72 insertions, 39 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 3f3f9494..75651a7a 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <wlr/types/wlr_buffer.h> | 10 | #include <wlr/types/wlr_buffer.h> |
11 | #include <wlr/types/wlr_drm_lease_v1.h> | 11 | #include <wlr/types/wlr_drm_lease_v1.h> |
12 | #include <wlr/types/wlr_matrix.h> | 12 | #include <wlr/types/wlr_matrix.h> |
13 | #include <wlr/types/wlr_output_damage.h> | ||
14 | #include <wlr/types/wlr_output_layout.h> | 13 | #include <wlr/types/wlr_output_layout.h> |
15 | #include <wlr/types/wlr_output.h> | 14 | #include <wlr/types/wlr_output.h> |
16 | #include <wlr/types/wlr_presentation_time.h> | 15 | #include <wlr/types/wlr_presentation_time.h> |
@@ -553,31 +552,43 @@ static int output_repaint_timer_handler(void *data) { | |||
553 | } | 552 | } |
554 | } | 553 | } |
555 | 554 | ||
556 | bool needs_frame; | 555 | int buffer_age; |
556 | if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { | ||
557 | return 0; | ||
558 | } | ||
559 | |||
557 | pixman_region32_t damage; | 560 | pixman_region32_t damage; |
558 | pixman_region32_init(&damage); | 561 | pixman_region32_init(&damage); |
559 | if (!wlr_output_damage_attach_render(output->damage, | 562 | wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); |
560 | &needs_frame, &damage)) { | 563 | if (!output->wlr_output->needs_frame && |
564 | !pixman_region32_not_empty(&output->damage_ring.current)) { | ||
565 | pixman_region32_fini(&damage); | ||
566 | wlr_output_rollback(output->wlr_output); | ||
561 | return 0; | 567 | return 0; |
562 | } | 568 | } |
563 | 569 | ||
564 | if (needs_frame) { | 570 | struct timespec now; |
565 | struct timespec now; | 571 | clock_gettime(CLOCK_MONOTONIC, &now); |
566 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
567 | 572 | ||
568 | output_render(output, &now, &damage); | 573 | output_render(output, &now, &damage); |
569 | } else { | ||
570 | wlr_output_rollback(output->wlr_output); | ||
571 | } | ||
572 | 574 | ||
573 | pixman_region32_fini(&damage); | 575 | pixman_region32_fini(&damage); |
574 | 576 | ||
575 | return 0; | 577 | return 0; |
576 | } | 578 | } |
577 | 579 | ||
578 | static void damage_handle_frame(struct wl_listener *listener, void *user_data) { | 580 | static void handle_damage(struct wl_listener *listener, void *user_data) { |
579 | struct sway_output *output = | 581 | struct sway_output *output = |
580 | wl_container_of(listener, output, damage_frame); | 582 | wl_container_of(listener, output, damage); |
583 | struct wlr_output_event_damage *event = user_data; | ||
584 | if (wlr_damage_ring_add(&output->damage_ring, event->damage)) { | ||
585 | wlr_output_schedule_frame(output->wlr_output); | ||
586 | } | ||
587 | } | ||
588 | |||
589 | static void handle_frame(struct wl_listener *listener, void *user_data) { | ||
590 | struct sway_output *output = | ||
591 | wl_container_of(listener, output, frame); | ||
581 | if (!output->enabled || !output->wlr_output->enabled) { | 592 | if (!output->enabled || !output->wlr_output->enabled) { |
582 | return; | 593 | return; |
583 | } | 594 | } |
@@ -640,11 +651,18 @@ static void damage_handle_frame(struct wl_listener *listener, void *user_data) { | |||
640 | send_frame_done(output, &data); | 651 | send_frame_done(output, &data); |
641 | } | 652 | } |
642 | 653 | ||
654 | static void handle_needs_frame(struct wl_listener *listener, void *user_data) { | ||
655 | struct sway_output *output = | ||
656 | wl_container_of(listener, output, needs_frame); | ||
657 | wlr_output_schedule_frame(output->wlr_output); | ||
658 | } | ||
659 | |||
643 | void output_damage_whole(struct sway_output *output) { | 660 | void output_damage_whole(struct sway_output *output) { |
644 | // The output can exist with no wlr_output if it's just been disconnected | 661 | // The output can exist with no wlr_output if it's just been disconnected |
645 | // and the transaction to evacuate it has't completed yet. | 662 | // and the transaction to evacuate it has't completed yet. |
646 | if (output && output->wlr_output && output->damage) { | 663 | if (output != NULL && output->wlr_output != NULL) { |
647 | wlr_output_damage_add_whole(output->damage); | 664 | wlr_damage_ring_add_whole(&output->damage_ring); |
665 | wlr_output_schedule_frame(output->wlr_output); | ||
648 | } | 666 | } |
649 | } | 667 | } |
650 | 668 | ||
@@ -668,11 +686,15 @@ static void damage_surface_iterator(struct sway_output *output, | |||
668 | ceil(output->wlr_output->scale) - surface->current.scale); | 686 | ceil(output->wlr_output->scale) - surface->current.scale); |
669 | } | 687 | } |
670 | pixman_region32_translate(&damage, box.x, box.y); | 688 | pixman_region32_translate(&damage, box.x, box.y); |
671 | wlr_output_damage_add(output->damage, &damage); | 689 | if (wlr_damage_ring_add(&output->damage_ring, &damage)) { |
690 | wlr_output_schedule_frame(output->wlr_output); | ||
691 | } | ||
672 | pixman_region32_fini(&damage); | 692 | pixman_region32_fini(&damage); |
673 | 693 | ||
674 | if (whole) { | 694 | if (whole) { |
675 | wlr_output_damage_add_box(output->damage, &box); | 695 | if (wlr_damage_ring_add_box(&output->damage_ring, &box)) { |
696 | wlr_output_schedule_frame(output->wlr_output); | ||
697 | } | ||
676 | } | 698 | } |
677 | 699 | ||
678 | if (!wl_list_empty(&surface->current.frame_callback_list)) { | 700 | if (!wl_list_empty(&surface->current.frame_callback_list)) { |
@@ -702,7 +724,9 @@ void output_damage_box(struct sway_output *output, struct wlr_box *_box) { | |||
702 | box.x -= output->lx; | 724 | box.x -= output->lx; |
703 | box.y -= output->ly; | 725 | box.y -= output->ly; |
704 | scale_box(&box, output->wlr_output->scale); | 726 | scale_box(&box, output->wlr_output->scale); |
705 | wlr_output_damage_add_box(output->damage, &box); | 727 | if (wlr_damage_ring_add_box(&output->damage_ring, &box)) { |
728 | wlr_output_schedule_frame(output->wlr_output); | ||
729 | } | ||
706 | } | 730 | } |
707 | 731 | ||
708 | static void damage_child_views_iterator(struct sway_container *con, | 732 | static void damage_child_views_iterator(struct sway_container *con, |
@@ -726,7 +750,9 @@ void output_damage_whole_container(struct sway_output *output, | |||
726 | .height = con->current.height + 2, | 750 | .height = con->current.height + 2, |
727 | }; | 751 | }; |
728 | scale_box(&box, output->wlr_output->scale); | 752 | scale_box(&box, output->wlr_output->scale); |
729 | wlr_output_damage_add_box(output->damage, &box); | 753 | if (wlr_damage_ring_add_box(&output->damage_ring, &box)) { |
754 | wlr_output_schedule_frame(output->wlr_output); | ||
755 | } | ||
730 | // Damage subsurfaces as well, which may extend outside the box | 756 | // Damage subsurfaces as well, which may extend outside the box |
731 | if (con->view) { | 757 | if (con->view) { |
732 | damage_child_views_iterator(con, output); | 758 | damage_child_views_iterator(con, output); |
@@ -735,20 +761,6 @@ void output_damage_whole_container(struct sway_output *output, | |||
735 | } | 761 | } |
736 | } | 762 | } |
737 | 763 | ||
738 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | ||
739 | struct sway_output *output = | ||
740 | wl_container_of(listener, output, damage_destroy); | ||
741 | if (!output->enabled) { | ||
742 | return; | ||
743 | } | ||
744 | output_disable(output); | ||
745 | |||
746 | wl_list_remove(&output->damage_destroy.link); | ||
747 | wl_list_remove(&output->damage_frame.link); | ||
748 | |||
749 | transaction_commit_dirty(); | ||
750 | } | ||
751 | |||
752 | static void update_output_manager_config(struct sway_server *server) { | 764 | static void update_output_manager_config(struct sway_server *server) { |
753 | struct wlr_output_configuration_v1 *config = | 765 | struct wlr_output_configuration_v1 *config = |
754 | wlr_output_configuration_v1_create(); | 766 | wlr_output_configuration_v1_create(); |
@@ -778,18 +790,24 @@ static void update_output_manager_config(struct sway_server *server) { | |||
778 | static void handle_destroy(struct wl_listener *listener, void *data) { | 790 | static void handle_destroy(struct wl_listener *listener, void *data) { |
779 | struct sway_output *output = wl_container_of(listener, output, destroy); | 791 | struct sway_output *output = wl_container_of(listener, output, destroy); |
780 | struct sway_server *server = output->server; | 792 | struct sway_server *server = output->server; |
781 | output_begin_destroy(output); | ||
782 | 793 | ||
783 | if (output->enabled) { | 794 | if (output->enabled) { |
784 | output_disable(output); | 795 | output_disable(output); |
785 | } | 796 | } |
786 | 797 | ||
798 | output_begin_destroy(output); | ||
799 | |||
787 | wl_list_remove(&output->link); | 800 | wl_list_remove(&output->link); |
788 | 801 | ||
789 | wl_list_remove(&output->destroy.link); | 802 | wl_list_remove(&output->destroy.link); |
790 | wl_list_remove(&output->commit.link); | 803 | wl_list_remove(&output->commit.link); |
791 | wl_list_remove(&output->mode.link); | 804 | wl_list_remove(&output->mode.link); |
792 | wl_list_remove(&output->present.link); | 805 | wl_list_remove(&output->present.link); |
806 | wl_list_remove(&output->damage.link); | ||
807 | wl_list_remove(&output->frame.link); | ||
808 | wl_list_remove(&output->needs_frame.link); | ||
809 | |||
810 | wlr_damage_ring_finish(&output->damage_ring); | ||
793 | 811 | ||
794 | output->wlr_output->data = NULL; | 812 | output->wlr_output->data = NULL; |
795 | output->wlr_output = NULL; | 813 | output->wlr_output = NULL; |
@@ -817,10 +835,15 @@ static void handle_mode(struct wl_listener *listener, void *data) { | |||
817 | if (!output->enabled) { | 835 | if (!output->enabled) { |
818 | return; | 836 | return; |
819 | } | 837 | } |
838 | |||
820 | arrange_layers(output); | 839 | arrange_layers(output); |
821 | arrange_output(output); | 840 | arrange_output(output); |
822 | transaction_commit_dirty(); | 841 | transaction_commit_dirty(); |
823 | 842 | ||
843 | wlr_damage_ring_set_bounds(&output->damage_ring, | ||
844 | output->width, output->height); | ||
845 | wlr_output_schedule_frame(output->wlr_output); | ||
846 | |||
824 | update_output_manager_config(output->server); | 847 | update_output_manager_config(output->server); |
825 | } | 848 | } |
826 | 849 | ||
@@ -848,6 +871,14 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
848 | 871 | ||
849 | update_output_manager_config(output->server); | 872 | update_output_manager_config(output->server); |
850 | } | 873 | } |
874 | |||
875 | if (event->committed & (WLR_OUTPUT_STATE_MODE | | ||
876 | WLR_OUTPUT_STATE_TRANSFORM | | ||
877 | WLR_OUTPUT_STATE_SCALE)) { | ||
878 | wlr_damage_ring_set_bounds(&output->damage_ring, | ||
879 | output->width, output->height); | ||
880 | wlr_output_schedule_frame(output->wlr_output); | ||
881 | } | ||
851 | } | 882 | } |
852 | 883 | ||
853 | static void handle_present(struct wl_listener *listener, void *data) { | 884 | static void handle_present(struct wl_listener *listener, void *data) { |
@@ -903,7 +934,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
903 | return; | 934 | return; |
904 | } | 935 | } |
905 | output->server = server; | 936 | output->server = server; |
906 | output->damage = wlr_output_damage_create(wlr_output); | 937 | wlr_damage_ring_init(&output->damage_ring); |
907 | 938 | ||
908 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | 939 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); |
909 | output->destroy.notify = handle_destroy; | 940 | output->destroy.notify = handle_destroy; |
@@ -913,10 +944,12 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
913 | output->mode.notify = handle_mode; | 944 | output->mode.notify = handle_mode; |
914 | wl_signal_add(&wlr_output->events.present, &output->present); | 945 | wl_signal_add(&wlr_output->events.present, &output->present); |
915 | output->present.notify = handle_present; | 946 | output->present.notify = handle_present; |
916 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | 947 | wl_signal_add(&wlr_output->events.damage, &output->damage); |
917 | output->damage_frame.notify = damage_handle_frame; | 948 | output->damage.notify = handle_damage; |
918 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | 949 | wl_signal_add(&wlr_output->events.frame, &output->frame); |
919 | output->damage_destroy.notify = damage_handle_destroy; | 950 | output->frame.notify = handle_frame; |
951 | wl_signal_add(&wlr_output->events.needs_frame, &output->needs_frame); | ||
952 | output->needs_frame.notify = handle_needs_frame; | ||
920 | 953 | ||
921 | output->repaint_timer = wl_event_loop_add_timer(server->wl_event_loop, | 954 | output->repaint_timer = wl_event_loop_add_timer(server->wl_event_loop, |
922 | output_repaint_timer_handler, output); | 955 | output_repaint_timer_handler, output); |