From 6f8eca2b3a13f1c534d20d85771e05971002b0ce Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 20 Feb 2018 15:06:52 +0100 Subject: [PATCH 1/3] rootston: send frame done events unconditionally --- rootston/output.c | 90 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/rootston/output.c b/rootston/output.c index 8ef383c3..9dc9899b 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -182,6 +182,21 @@ static void xwayland_children_for_each_surface( } #endif +static void drag_icons_for_each_surface(struct roots_input *input, + surface_iterator_func_t iterator, void *user_data) { + struct roots_seat *seat; + wl_list_for_each(seat, &input->seats, link) { + struct roots_drag_icon *drag_icon; + wl_list_for_each(drag_icon, &seat->drag_icons, link) { + if (!drag_icon->wlr_drag_icon->mapped) { + continue; + } + surface_for_each_surface(drag_icon->wlr_drag_icon->surface, + drag_icon->x, drag_icon->y, 0, iterator, user_data); + } + } +} + struct render_data { struct roots_output *output; @@ -190,18 +205,22 @@ struct render_data { }; /** - * Checks whether a surface at (lx, ly) intersects an output. Sets `box` to the - * surface box in the output, in output-local coordinates. + * Checks whether a surface at (lx, ly) intersects an output. If `box` is not + * NULL, it populates it with the surface box in the output, in output-local + * coordinates. */ static bool surface_intersect_output(struct wlr_surface *surface, struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, double lx, double ly, float rotation, struct wlr_box *box) { double ox = lx, oy = ly; wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); - box->x = ox * wlr_output->scale; - box->y = oy * wlr_output->scale; - box->width = surface->current->width * wlr_output->scale; - box->height = surface->current->height * wlr_output->scale; + + if (box != NULL) { + box->x = ox * wlr_output->scale; + box->y = oy * wlr_output->scale; + box->width = surface->current->width * wlr_output->scale; + box->height = surface->current->height * wlr_output->scale; + } struct wlr_box layout_box = { .x = lx, .y = ly, @@ -239,7 +258,6 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly, float rotation, void *_data) { struct render_data *data = _data; struct roots_output *output = data->output; - struct timespec *when = data->when; struct wlr_renderer *renderer = wlr_backend_get_renderer(output->wlr_output->backend); assert(renderer); @@ -281,8 +299,6 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly, wlr_render_with_matrix(renderer, surface->texture, &matrix); } - wlr_surface_send_frame_done(surface, when); - damage_finish: pixman_region32_fini(&damage); } @@ -384,6 +400,20 @@ static bool has_standalone_surface(struct roots_view *view) { return true; } +static void surface_send_frame_done(struct wlr_surface *surface, double lx, + double ly, float rotation, void *_data) { + struct render_data *data = _data; + struct roots_output *output = data->output; + struct timespec *when = data->when; + + if (!surface_intersect_output(surface, output->desktop->layout, + output->wlr_output, lx, ly, rotation, NULL)) { + return; + } + + wlr_surface_send_frame_done(surface, when); +} + static void render_output(struct roots_output *output) { struct wlr_output *wlr_output = output->wlr_output; struct roots_desktop *desktop = output->desktop; @@ -434,17 +464,17 @@ static void render_output(struct roots_output *output) { return; } - if (!needs_swap) { - // Output doesn't need swap and isn't damaged, skip rendering completely - goto damage_finish; - } - struct render_data data = { .output = output, .when = &now, .damage = &damage, }; + if (!needs_swap) { + // Output doesn't need swap and isn't damaged, skip rendering completely + goto damage_finish; + } + wlr_renderer_begin(renderer, wlr_output); if (!pixman_region32_not_empty(&damage)) { @@ -490,17 +520,7 @@ static void render_output(struct roots_output *output) { } // Render drag icons - struct roots_drag_icon *drag_icon = NULL; - struct roots_seat *seat = NULL; - wl_list_for_each(seat, &server->input->seats, link) { - wl_list_for_each(drag_icon, &seat->drag_icons, link) { - if (!drag_icon->wlr_drag_icon->mapped) { - continue; - } - render_surface(drag_icon->wlr_drag_icon->surface, - drag_icon->x, drag_icon->y, 0, &data); - } - } + drag_icons_for_each_surface(server->input, render_surface, &data); renderer_end: wlr_renderer_scissor(renderer, NULL); @@ -512,6 +532,26 @@ renderer_end: damage_finish: pixman_region32_fini(&damage); + + // Send frame done events to all surfaces + if (output->fullscreen_view != NULL) { + view_for_each_surface(view, surface_send_frame_done, &data); + +#ifdef WLR_HAS_XWAYLAND + if (view->type == ROOTS_XWAYLAND_VIEW) { + xwayland_children_for_each_surface(view->xwayland_surface, + surface_send_frame_done, &data); + } +#endif + } else { + struct roots_view *view; + wl_list_for_each_reverse(view, &desktop->views, link) { + view_for_each_surface(view, surface_send_frame_done, &data); + } + + drag_icons_for_each_surface(server->input, surface_send_frame_done, + &data); + } } static void output_damage_handle_frame(struct wl_listener *listener, From dc77b4c8c648c9a19b540fa3402d5400523fa452 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 20 Feb 2018 16:17:23 +0100 Subject: [PATCH 2/3] rootston: don't send frame done if wlr_output manages the surface --- rootston/output.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rootston/output.c b/rootston/output.c index 9dc9899b..127fec78 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -535,6 +535,11 @@ damage_finish: // Send frame done events to all surfaces if (output->fullscreen_view != NULL) { + if (wlr_output->fullscreen_surface == output->fullscreen_view->wlr_surface) { + // The surface is managed by the wlr_output + return; + } + view_for_each_surface(view, surface_send_frame_done, &data); #ifdef WLR_HAS_XWAYLAND From 00e647e16126e2557d23b04db2eace3d57ae20e4 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 20 Feb 2018 16:32:29 +0100 Subject: [PATCH 3/3] rootston: fix sending frame done to undefined view --- rootston/output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rootston/output.c b/rootston/output.c index 127fec78..b47d9129 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -535,7 +535,8 @@ damage_finish: // Send frame done events to all surfaces if (output->fullscreen_view != NULL) { - if (wlr_output->fullscreen_surface == output->fullscreen_view->wlr_surface) { + struct roots_view *view = output->fullscreen_view; + if (wlr_output->fullscreen_surface == view->wlr_surface) { // The surface is managed by the wlr_output return; }