diff options
-rw-r--r-- | sway/desktop/output.c | 96 | ||||
-rw-r--r-- | sway/desktop/render.c | 85 |
2 files changed, 96 insertions, 85 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 4bfc3b77..7f250542 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -412,6 +412,72 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
412 | output_for_each_surface(output, send_frame_done_iterator, when); | 412 | output_for_each_surface(output, send_frame_done_iterator, when); |
413 | } | 413 | } |
414 | 414 | ||
415 | static void count_surface_iterator(struct sway_output *output, | ||
416 | struct wlr_surface *surface, struct wlr_box *_box, float rotation, | ||
417 | void *data) { | ||
418 | size_t *n = data; | ||
419 | (*n)++; | ||
420 | } | ||
421 | |||
422 | static bool scan_out_fullscreen_view(struct sway_output *output, | ||
423 | struct sway_view *view) { | ||
424 | struct wlr_output *wlr_output = output->wlr_output; | ||
425 | struct sway_workspace *workspace = output->current.active_workspace; | ||
426 | if (!sway_assert(workspace, "Expected an active workspace")) { | ||
427 | return false; | ||
428 | } | ||
429 | |||
430 | if (view->saved_buffer) { | ||
431 | return false; | ||
432 | } | ||
433 | |||
434 | for (int i = 0; i < workspace->current.floating->length; ++i) { | ||
435 | struct sway_container *floater = | ||
436 | workspace->current.floating->items[i]; | ||
437 | if (container_is_transient_for(floater, view->container)) { | ||
438 | return false; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | #if HAVE_XWAYLAND | ||
443 | if (!wl_list_empty(&root->xwayland_unmanaged)) { | ||
444 | return false; | ||
445 | } | ||
446 | #endif | ||
447 | |||
448 | if (!wl_list_empty(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY])) { | ||
449 | return false; | ||
450 | } | ||
451 | if (!wl_list_empty(&root->drag_icons)) { | ||
452 | return false; | ||
453 | } | ||
454 | |||
455 | struct wlr_surface *surface = view->surface; | ||
456 | if (surface == NULL) { | ||
457 | return false; | ||
458 | } | ||
459 | size_t n_surfaces = 0; | ||
460 | output_view_for_each_surface(output, view, | ||
461 | count_surface_iterator, &n_surfaces); | ||
462 | if (n_surfaces != 1) { | ||
463 | return false; | ||
464 | } | ||
465 | |||
466 | if (surface->buffer == NULL) { | ||
467 | return false; | ||
468 | } | ||
469 | |||
470 | if ((float)surface->current.scale != wlr_output->scale || | ||
471 | surface->current.transform != wlr_output->transform) { | ||
472 | return false; | ||
473 | } | ||
474 | |||
475 | if (!wlr_output_attach_buffer(wlr_output, surface->buffer)) { | ||
476 | return false; | ||
477 | } | ||
478 | return wlr_output_commit(wlr_output); | ||
479 | } | ||
480 | |||
415 | static void damage_handle_frame(struct wl_listener *listener, void *data) { | 481 | static void damage_handle_frame(struct wl_listener *listener, void *data) { |
416 | struct sway_output *output = | 482 | struct sway_output *output = |
417 | wl_container_of(listener, output, damage_frame); | 483 | wl_container_of(listener, output, damage_frame); |
@@ -422,6 +488,35 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) { | |||
422 | struct timespec now; | 488 | struct timespec now; |
423 | clock_gettime(CLOCK_MONOTONIC, &now); | 489 | clock_gettime(CLOCK_MONOTONIC, &now); |
424 | 490 | ||
491 | struct sway_workspace *workspace = output->current.active_workspace; | ||
492 | if (workspace == NULL) { | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | struct sway_container *fullscreen_con = root->fullscreen_global; | ||
497 | if (!fullscreen_con) { | ||
498 | fullscreen_con = workspace->current.fullscreen; | ||
499 | } | ||
500 | |||
501 | if (fullscreen_con && fullscreen_con->view) { | ||
502 | // Try to scan-out the fullscreen view | ||
503 | static bool last_scanned_out = false; | ||
504 | bool scanned_out = | ||
505 | scan_out_fullscreen_view(output, fullscreen_con->view); | ||
506 | |||
507 | if (scanned_out && !last_scanned_out) { | ||
508 | sway_log(SWAY_DEBUG, "Scanning out fullscreen view"); | ||
509 | } | ||
510 | if (last_scanned_out && !scanned_out) { | ||
511 | sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out"); | ||
512 | } | ||
513 | last_scanned_out = scanned_out; | ||
514 | |||
515 | if (scanned_out) { | ||
516 | goto frame_done; | ||
517 | } | ||
518 | } | ||
519 | |||
425 | bool needs_frame; | 520 | bool needs_frame; |
426 | pixman_region32_t damage; | 521 | pixman_region32_t damage; |
427 | pixman_region32_init(&damage); | 522 | pixman_region32_init(&damage); |
@@ -436,6 +531,7 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) { | |||
436 | 531 | ||
437 | pixman_region32_fini(&damage); | 532 | pixman_region32_fini(&damage); |
438 | 533 | ||
534 | frame_done: | ||
439 | // Send frame done to all visible surfaces | 535 | // Send frame done to all visible surfaces |
440 | send_frame_done(output, &now); | 536 | send_frame_done(output, &now); |
441 | } | 537 | } |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 5cec5949..916d4eba 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -927,72 +927,6 @@ static void render_seatops(struct sway_output *output, | |||
927 | } | 927 | } |
928 | } | 928 | } |
929 | 929 | ||
930 | static void count_surface_iterator(struct sway_output *output, | ||
931 | struct wlr_surface *surface, struct wlr_box *_box, float rotation, | ||
932 | void *data) { | ||
933 | size_t *n = data; | ||
934 | (*n)++; | ||
935 | } | ||
936 | |||
937 | static bool scan_out_fullscreen_view(struct sway_output *output, | ||
938 | struct sway_view *view) { | ||
939 | struct wlr_output *wlr_output = output->wlr_output; | ||
940 | struct sway_workspace *workspace = output->current.active_workspace; | ||
941 | if (!sway_assert(workspace, "Expected an active workspace")) { | ||
942 | return false; | ||
943 | } | ||
944 | |||
945 | if (view->saved_buffer) { | ||
946 | return false; | ||
947 | } | ||
948 | |||
949 | for (int i = 0; i < workspace->current.floating->length; ++i) { | ||
950 | struct sway_container *floater = | ||
951 | workspace->current.floating->items[i]; | ||
952 | if (container_is_transient_for(floater, view->container)) { | ||
953 | return false; | ||
954 | } | ||
955 | } | ||
956 | |||
957 | #if HAVE_XWAYLAND | ||
958 | if (!wl_list_empty(&root->xwayland_unmanaged)) { | ||
959 | return false; | ||
960 | } | ||
961 | #endif | ||
962 | |||
963 | if (!wl_list_empty(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY])) { | ||
964 | return false; | ||
965 | } | ||
966 | if (!wl_list_empty(&root->drag_icons)) { | ||
967 | return false; | ||
968 | } | ||
969 | |||
970 | struct wlr_surface *surface = view->surface; | ||
971 | if (surface == NULL) { | ||
972 | return false; | ||
973 | } | ||
974 | size_t n_surfaces = 0; | ||
975 | output_view_for_each_surface(output, view, | ||
976 | count_surface_iterator, &n_surfaces); | ||
977 | if (n_surfaces != 1) { | ||
978 | return false; | ||
979 | } | ||
980 | |||
981 | if (surface->buffer == NULL) { | ||
982 | return false; | ||
983 | } | ||
984 | |||
985 | if ((float)surface->current.scale != wlr_output->scale || | ||
986 | surface->current.transform != wlr_output->transform) { | ||
987 | return false; | ||
988 | } | ||
989 | |||
990 | if (!wlr_output_attach_buffer(wlr_output, surface->buffer)) { | ||
991 | return false; | ||
992 | } | ||
993 | return wlr_output_commit(wlr_output); | ||
994 | } | ||
995 | |||
996 | void output_render(struct sway_output *output, struct timespec *when, | 930 | void output_render(struct sway_output *output, struct timespec *when, |
997 | pixman_region32_t *damage) { | 931 | pixman_region32_t *damage) { |
998 | struct wlr_output *wlr_output = output->wlr_output; | 932 | struct wlr_output *wlr_output = output->wlr_output; |
@@ -1014,25 +948,6 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
1014 | fullscreen_con = workspace->current.fullscreen; | 948 | fullscreen_con = workspace->current.fullscreen; |
1015 | } | 949 | } |
1016 | 950 | ||
1017 | if (fullscreen_con && fullscreen_con->view) { | ||
1018 | // Try to scan-out the fullscreen view | ||
1019 | static bool last_scanned_out = false; | ||
1020 | bool scanned_out = | ||
1021 | scan_out_fullscreen_view(output, fullscreen_con->view); | ||
1022 | |||
1023 | if (scanned_out && !last_scanned_out) { | ||
1024 | sway_log(SWAY_DEBUG, "Scanning out fullscreen view"); | ||
1025 | } | ||
1026 | if (last_scanned_out && !scanned_out) { | ||
1027 | sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out"); | ||
1028 | } | ||
1029 | last_scanned_out = scanned_out; | ||
1030 | |||
1031 | if (scanned_out) { | ||
1032 | return; | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); | 951 | wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); |
1037 | 952 | ||
1038 | if (!pixman_region32_not_empty(damage)) { | 953 | if (!pixman_region32_not_empty(damage)) { |