From d5940c396ce6634cd1d05078b2e43f786e27ccd2 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Sun, 8 May 2022 08:25:15 +0000 Subject: [PATCH] Render using wlr_scene Apart from removing a lot of code, this commit also introduces (thanks to wlr_scene) fine-grained damage tracking. The lack of our own rendering code will only be an issue if the need for custom effects (such as blur) arises; however, that's very unlikely and it would probably require a lot of changes anyway. --- include/desktop/output.h | 4 - kiwmi/desktop/layer_shell.c | 3 - kiwmi/desktop/output.c | 225 ++---------------------------------- kiwmi/desktop/view.c | 43 +------ kiwmi/desktop/xdg_shell.c | 21 ---- kiwmi/input/seat.c | 8 -- 6 files changed, 13 insertions(+), 291 deletions(-) diff --git a/include/desktop/output.h b/include/desktop/output.h index 1ebd018..1b579e6 100644 --- a/include/desktop/output.h +++ b/include/desktop/output.h @@ -28,8 +28,6 @@ struct kiwmi_output { struct wlr_box usable_area; - int damaged; - struct { struct wl_signal destroy; struct wl_signal resize; @@ -49,6 +47,4 @@ struct kiwmi_render_data { void new_output_notify(struct wl_listener *listener, void *data); void output_layout_change_notify(struct wl_listener *listener, void *data); -void output_damage(struct kiwmi_output *output); - #endif /* KIWMI_DESKTOP_OUTPUT_H */ diff --git a/kiwmi/desktop/layer_shell.c b/kiwmi/desktop/layer_shell.c index f132580..424fed6 100644 --- a/kiwmi/desktop/layer_shell.c +++ b/kiwmi/desktop/layer_shell.c @@ -61,7 +61,6 @@ kiwmi_layer_commit_notify(struct wl_listener *listener, void *UNUSED(data)) } if (layer->layer_surface->current.committed != 0) { - output_damage(layer->output); arrange_layers(output); } } @@ -75,7 +74,6 @@ kiwmi_layer_map_notify(struct wl_listener *listener, void *UNUSED(data)) wlr_scene_node_set_enabled(&layer->desktop_surface.popups_tree->node, true); arrange_layers(layer->output); - output_damage(layer->output); } static void @@ -88,7 +86,6 @@ kiwmi_layer_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) &layer->desktop_surface.popups_tree->node, false); arrange_layers(layer->output); - output_damage(layer->output); } static void diff --git a/kiwmi/desktop/output.c b/kiwmi/desktop/output.c index e3e66c1..51de01c 100644 --- a/kiwmi/desktop/output.c +++ b/kiwmi/desktop/output.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,216 +31,24 @@ #include "input/pointer.h" #include "server.h" -static void -render_layer_surface(struct wlr_surface *surface, int x, int y, void *data) -{ - struct kiwmi_render_data *rdata = data; - struct wlr_output *wlr_output = rdata->output; - struct wlr_box *geom = rdata->data; - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (!texture) { - return; - } - - int ox = x + geom->x; - int oy = y + geom->y; - - struct wlr_box box = { - .x = ox * wlr_output->scale, - .y = oy * wlr_output->scale, - .width = surface->current.width * wlr_output->scale, - .height = surface->current.height * wlr_output->scale, - }; - - float matrix[9]; - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box( - matrix, &box, transform, 0, wlr_output->transform_matrix); - - wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); - - wlr_surface_send_frame_done(surface, rdata->when); -} - -static void -render_layer(struct wl_list *layer, struct kiwmi_render_data *rdata) -{ - struct kiwmi_layer *surface; - wl_list_for_each (surface, layer, link) { - rdata->data = &surface->geom; - - wlr_layer_surface_v1_for_each_surface( - surface->layer_surface, render_layer_surface, rdata); - } -} - -static void -send_frame_done_to_layer_surface( - struct wlr_surface *surface, - int UNUSED(x), - int UNUSED(y), - void *data) -{ - struct timespec *now = data; - wlr_surface_send_frame_done(surface, now); -} - -static void -send_frame_done_to_layer(struct wl_list *layer, struct timespec *now) -{ - struct kiwmi_layer *surface; - wl_list_for_each (surface, layer, link) { - wlr_layer_surface_v1_for_each_surface( - surface->layer_surface, send_frame_done_to_layer_surface, now); - } -} - -static void -render_surface(struct wlr_surface *surface, int sx, int sy, void *data) -{ - struct kiwmi_render_data *rdata = data; - struct kiwmi_view *view = rdata->data; - struct wlr_output *wlr_output = rdata->output; - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (!texture) { - return; - } - - int ox = rdata->output_lx + sx + view->x - view->geom.x; - int oy = rdata->output_ly + sy + view->y - view->geom.y; - - struct wlr_box box = { - .x = ox * wlr_output->scale, - .y = oy * wlr_output->scale, - .width = surface->current.width * wlr_output->scale, - .height = surface->current.height * wlr_output->scale, - }; - - float matrix[9]; - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box( - matrix, &box, transform, 0, wlr_output->transform_matrix); - - wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); - - wlr_surface_send_frame_done(surface, rdata->when); -} - -static void -send_frame_done_to_surface( - struct wlr_surface *surface, - int UNUSED(sx), - int UNUSED(sy), - void *data) -{ - struct timespec *now = data; - wlr_surface_send_frame_done(surface, now); -} - -static bool -render_cursors(struct wlr_output *wlr_output) -{ - pixman_region32_t damage; - pixman_region32_init(&damage); - wlr_output_render_software_cursors(wlr_output, &damage); - bool damaged = pixman_region32_not_empty(&damage); - pixman_region32_fini(&damage); - - return damaged; -} - static void output_frame_notify(struct wl_listener *listener, void *data) { struct kiwmi_output *output = wl_container_of(listener, output, frame); struct wlr_output *wlr_output = data; - struct kiwmi_desktop *desktop = output->desktop; + + struct wlr_scene_output *scene_output = + wlr_scene_get_scene_output(output->desktop->scene, wlr_output); + + if (!scene_output) { + return; + } + + wlr_scene_output_commit(scene_output); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - - int buffer_age; - if (!wlr_output_attach_render(wlr_output, &buffer_age)) { - wlr_log(WLR_ERROR, "Failed to attach renderer to output"); - return; - } - - if (output->damaged == 0 && buffer_age > 0) { - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); - send_frame_done_to_layer( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); - - struct kiwmi_view *view; - wl_list_for_each (view, &desktop->views, link) { - view_for_each_surface(view, send_frame_done_to_surface, &now); - } - - if (render_cursors(wlr_output)) { - output_damage(output); - } - - wlr_output_commit(wlr_output); - return; - } - - struct wlr_output_layout *output_layout = desktop->output_layout; - struct kiwmi_server *server = wl_container_of(desktop, server, desktop); - struct wlr_renderer *renderer = server->renderer; - - wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); - wlr_renderer_clear(renderer, desktop->bg_color); - - double output_lx = 0; - double output_ly = 0; - wlr_output_layout_output_coords( - output_layout, wlr_output, &output_lx, &output_ly); - - struct kiwmi_render_data rdata = { - .output = output->wlr_output, - .output_lx = output_lx, - .output_ly = output_ly, - .renderer = renderer, - .when = &now, - }; - - render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &rdata); - render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &rdata); - - struct kiwmi_view *view; - wl_list_for_each_reverse (view, &desktop->views, link) { - if (view->hidden || !view->mapped) { - continue; - } - - rdata.data = view; - - wl_signal_emit(&view->events.pre_render, &rdata); - view_for_each_surface(view, render_surface, &rdata); - wl_signal_emit(&view->events.post_render, &rdata); - } - - render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &rdata); - render_layer(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &rdata); - - bool damaged = render_cursors(wlr_output); - wlr_renderer_end(renderer); - - if (damaged) { - output_damage(output); - } else { - --output->damaged; - } - - wlr_output_commit(wlr_output); + wlr_scene_output_send_frame_done(scene_output, &now); } static void @@ -250,7 +59,6 @@ output_commit_notify(struct wl_listener *listener, void *data) if (event->committed & WLR_OUTPUT_STATE_TRANSFORM) { arrange_layers(output); - output_damage(output); wl_signal_emit(&output->events.resize, output); } @@ -304,7 +112,6 @@ output_mode_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - output_damage(output); wl_signal_emit(&output->events.resize, output); } @@ -335,8 +142,6 @@ output_create(struct wlr_output *wlr_output, struct kiwmi_desktop *desktop) output->mode.notify = output_mode_notify; wl_signal_add(&wlr_output->events.mode, &output->mode); - output_damage(output); - return output; } @@ -408,14 +213,6 @@ new_output_notify(struct wl_listener *listener, void *data) wl_signal_emit(&desktop->events.new_output, output); } -void -output_damage(struct kiwmi_output *output) -{ - if (output != NULL) { - output->damaged = 2; - } -} - void output_layout_change_notify(struct wl_listener *listener, void *UNUSED(data)) { diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index 24f5481..8785c9b 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -92,11 +92,6 @@ view_set_size(struct kiwmi_view *view, uint32_t width, uint32_t height) child->impl->reconfigure(child); } } - - struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { - output_damage(output); - } } } @@ -120,11 +115,6 @@ view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) struct kiwmi_server *server = wl_container_of(desktop, server, desktop); struct kiwmi_cursor *cursor = server->input.cursor; cursor_refresh_focus(cursor, NULL, NULL, NULL); - - struct kiwmi_output *output; - wl_list_for_each (output, &desktop->outputs, link) { - output_damage(output); - } } void @@ -355,24 +345,9 @@ view_child_is_mapped(struct kiwmi_view_child *child) return child->view->mapped; } -void -view_child_damage(struct kiwmi_view_child *child) -{ - // Note for later: this is supposed to damage the child and all subchildren - struct kiwmi_output *output; - wl_list_for_each (output, &child->view->desktop->outputs, link) { - output_damage(output); - } -} - void view_child_destroy(struct kiwmi_view_child *child) { - bool visible = view_child_is_mapped(child) && !child->view->hidden; - if (visible) { - view_child_damage(child); - } - wl_list_remove(&child->link); child->parent = NULL; @@ -414,12 +389,8 @@ view_child_surface_destroy_notify( } static void -view_child_commit_notify(struct wl_listener *listener, void *UNUSED(data)) +view_child_commit_notify() { - struct kiwmi_view_child *child = wl_container_of(listener, child, commit); - if (view_child_is_mapped(child)) { - view_child_damage(child); - } } static void @@ -436,19 +407,13 @@ view_child_map_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view_child *child = wl_container_of(listener, child, map); child->mapped = true; - if (view_child_is_mapped(child)) { - view_child_damage(child); - } } static void view_child_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view_child *child = wl_container_of(listener, child, unmap); - if (view_child_is_mapped(child)) { - view_child_damage(child); - } - child->mapped = false; + child->mapped = false; } struct kiwmi_view_child * @@ -520,10 +485,6 @@ view_child_subsurface_create( child->wlr_subsurface = subsurface; child->mapped = subsurface->mapped; - if (view_child_is_mapped(child)) { - view_child_damage(child); - } - wl_signal_add(&subsurface->events.map, &child->map); wl_signal_add(&subsurface->events.unmap, &child->unmap); diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 4b12139..493ca9c 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -137,10 +137,6 @@ view_child_popup_create( child->wlr_xdg_popup = wlr_popup; child->mapped = wlr_popup->base->mapped; - if (view_child_is_mapped(child)) { - view_child_damage(child); - } - wl_signal_add(&wlr_popup->base->events.map, &child->map); wl_signal_add(&wlr_popup->base->events.unmap, &child->unmap); @@ -177,11 +173,6 @@ xdg_surface_map_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_view *view = wl_container_of(listener, view, map); view->mapped = true; - struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { - output_damage(output); - } - wl_signal_emit(&view->desktop->events.view_map, view); } @@ -201,11 +192,6 @@ xdg_surface_unmap_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_server *server = wl_container_of(desktop, server, desktop); cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); - struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { - output_damage(output); - } - wl_signal_emit(&view->events.unmap, view); } } @@ -220,13 +206,6 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data)) struct kiwmi_cursor *cursor = server->input.cursor; cursor_refresh_focus(cursor, NULL, NULL, NULL); - if (pixman_region32_not_empty(&view->wlr_surface->buffer_damage)) { - struct kiwmi_output *output; - wl_list_for_each (output, &desktop->outputs, link) { - output_damage(output); - } - } - wlr_xdg_surface_get_geometry(view->xdg_surface, &view->geom); } diff --git a/kiwmi/input/seat.c b/kiwmi/input/seat.c index d8c62d5..d528673 100644 --- a/kiwmi/input/seat.c +++ b/kiwmi/input/seat.c @@ -116,14 +116,6 @@ request_set_cursor_notify(struct wl_listener *listener, void *data) return; } - struct kiwmi_input *input = seat->input; - struct kiwmi_server *server = wl_container_of(input, server, input); - - struct kiwmi_output *output; - wl_list_for_each (output, &server->desktop.outputs, link) { - output_damage(output); - } - wlr_cursor_set_surface( cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y); }