From cfe2209a0cec881373c4960f2a589852c8805fa8 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 27 Apr 2023 11:19:58 +0200 Subject: [PATCH 1/3] render: pass rendering state together in a struct This lets us easily add rendering state that we need in the future --- include/sway/input/seat.h | 7 +- include/sway/output.h | 11 +- sway/desktop/output.c | 14 +- sway/desktop/render.c | 269 +++++++++++++++----------------- sway/input/seat.c | 5 +- sway/input/seatop_move_tiling.c | 9 +- 6 files changed, 156 insertions(+), 159 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 7b2d3d0759..6d29cf3bf3 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -12,6 +12,7 @@ #include "sway/input/text_input.h" struct sway_seat; +struct render_context; struct sway_seatop_impl { void (*button)(struct sway_seat *seat, uint32_t time_msec, @@ -49,8 +50,7 @@ struct sway_seatop_impl { uint32_t time_msec, enum wlr_tablet_tool_tip_state state); void (*end)(struct sway_seat *seat); void (*unref)(struct sway_seat *seat, struct sway_container *con); - void (*render)(struct sway_seat *seat, struct sway_output *output, - const pixman_region32_t *damage); + void (*render)(struct sway_seat *seat, struct render_context *ctx); bool allow_set_cursor; }; @@ -356,8 +356,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con); * Instructs a seatop to render anything that it needs to render * (eg. dropzone for move-tiling) */ -void seatop_render(struct sway_seat *seat, struct sway_output *output, - const pixman_region32_t *damage); +void seatop_render(struct sway_seat *seat, struct render_context *ctx); bool seatop_allows_set_cursor(struct sway_seat *seat); diff --git a/include/sway/output.h b/include/sway/output.h index 04202976c7..b397c8e2d3 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -65,6 +65,12 @@ struct sway_output_non_desktop { struct wl_listener destroy; }; +struct render_context { + struct sway_output *output; + struct wlr_renderer *renderer; + const pixman_region32_t *output_damage; +}; + struct sway_output *output_create(struct wlr_output *wlr_output); void output_destroy(struct sway_output *output); @@ -115,7 +121,7 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output); struct sway_workspace *output_get_active_workspace(struct sway_output *output); -void output_render(struct sway_output *output, pixman_region32_t *damage); +void output_render(struct render_context *ctx); void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, @@ -168,8 +174,7 @@ void output_get_box(struct sway_output *output, struct wlr_box *box); enum sway_container_layout output_get_default_layout( struct sway_output *output); -void render_rect(struct sway_output *output, - const pixman_region32_t *output_damage, const struct wlr_box *_box, +void render_rect(struct render_context *ctx, const struct wlr_box *_box, float color[static 4]); void premultiply_alpha(float color[4], float opacity); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2255b5518b..02e08bd2d3 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -613,10 +613,22 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_init(&damage); wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); + if (debug.damage == DAMAGE_RERENDER) { + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(&damage, &damage, 0, 0, width, height); + } + + struct render_context ctx = { + .output_damage = &damage, + .renderer = wlr_output->renderer, + .output = output, + }; + struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - output_render(output, &damage); + output_render(&ctx); pixman_region32_fini(&damage); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a4d633e094..f011e0ffe3 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,6 +32,7 @@ #endif struct render_data { + struct render_context *ctx; const pixman_region32_t *damage; float alpha; struct wlr_box *clip_box; @@ -101,18 +102,17 @@ static void set_scale_filter(struct wlr_output *wlr_output, #endif } -static void render_texture(struct wlr_output *wlr_output, - const pixman_region32_t *output_damage, struct wlr_texture *texture, +static void render_texture(struct render_context *ctx, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], float alpha) { - struct wlr_renderer *renderer = wlr_output->renderer; - struct sway_output *output = wlr_output->data; + struct wlr_renderer *renderer = ctx->renderer; + struct sway_output *output = ctx->output; pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, dst_box->width, dst_box->height); - pixman_region32_intersect(&damage, &damage, output_damage); + pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; @@ -121,8 +121,8 @@ static void render_texture(struct wlr_output *wlr_output, int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - set_scale_filter(wlr_output, texture, output->scale_filter); + scissor_output(output->wlr_output, &rects[i]); + set_scale_filter(output->wlr_output, texture, output->scale_filter); if (src_box != NULL) { wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, alpha); } else { @@ -139,7 +139,6 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_box *_box, void *_data) { struct render_data *data = _data; struct wlr_output *wlr_output = output->wlr_output; - const pixman_region32_t *output_damage = data->damage; float alpha = data->alpha; struct wlr_texture *texture = wlr_surface_get_texture(surface); @@ -167,73 +166,68 @@ static void render_surface_iterator(struct sway_output *output, } scale_box(&dst_box, wlr_output->scale); - render_texture(wlr_output, output_damage, texture, + render_texture(data->ctx, texture, &src_box, &dst_box, matrix, alpha); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); } -static void render_layer_toplevel(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *layer_surfaces) { +static void render_layer_toplevel(struct render_context *ctx, struct wl_list *layer_surfaces) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_layer_for_each_toplevel_surface(output, layer_surfaces, + output_layer_for_each_toplevel_surface(ctx->output, layer_surfaces, render_surface_iterator, &data); } -static void render_layer_popups(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *layer_surfaces) { +static void render_layer_popups(struct render_context *ctx, struct wl_list *layer_surfaces) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_layer_for_each_popup_surface(output, layer_surfaces, + output_layer_for_each_popup_surface(ctx->output, layer_surfaces, render_surface_iterator, &data); } #if HAVE_XWAYLAND -static void render_unmanaged(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *unmanaged) { +static void render_unmanaged(struct render_context *ctx, struct wl_list *unmanaged) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_unmanaged_for_each_surface(output, unmanaged, + output_unmanaged_for_each_surface(ctx->output, unmanaged, render_surface_iterator, &data); } #endif -static void render_drag_icons(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *drag_icons) { +static void render_drag_icons(struct render_context *ctx, struct wl_list *drag_icons) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_drag_icons_for_each_surface(output, drag_icons, + output_drag_icons_for_each_surface(ctx->output, drag_icons, render_surface_iterator, &data); } // _box.x and .y are expected to be layout-local // _box.width and .height are expected to be output-buffer-local -void render_rect(struct sway_output *output, - const pixman_region32_t *output_damage, const struct wlr_box *_box, +void render_rect(struct render_context *ctx, const struct wlr_box *_box, float color[static 4]) { - struct wlr_output *wlr_output = output->wlr_output; - struct wlr_renderer *renderer = wlr_output->renderer; + struct wlr_output *wlr_output = ctx->output->wlr_output; + struct wlr_renderer *renderer = ctx->renderer; struct wlr_box box; memcpy(&box, _box, sizeof(struct wlr_box)); - box.x -= output->lx * wlr_output->scale; - box.y -= output->ly * wlr_output->scale; + box.x -= ctx->output->lx * wlr_output->scale; + box.y -= ctx->output->ly * wlr_output->scale; pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, box.x, box.y, box.width, box.height); - pixman_region32_intersect(&damage, &damage, output_damage); + pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; @@ -258,11 +252,11 @@ void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_toplevels(struct sway_view *view, - struct sway_output *output, const pixman_region32_t *damage, float alpha) { +static void render_view_toplevels(struct render_context *ctx, + struct sway_view *view, float alpha) { struct render_data data = { - .damage = damage, .alpha = alpha, + .ctx = ctx, }; struct wlr_box clip_box; if (!container_is_current_floating(view->container)) { @@ -274,25 +268,26 @@ static void render_view_toplevels(struct sway_view *view, } // Render all toplevels without descending into popups double ox = view->container->surface_x - - output->lx - view->geometry.x; + ctx->output->lx - view->geometry.x; double oy = view->container->surface_y - - output->ly - view->geometry.y; - output_surface_for_each_surface(output, view->surface, ox, oy, + ctx->output->ly - view->geometry.y; + output_surface_for_each_surface(ctx->output, view->surface, ox, oy, render_surface_iterator, &data); } -static void render_view_popups(struct sway_view *view, - struct sway_output *output, const pixman_region32_t *damage, float alpha) { +static void render_view_popups(struct render_context *ctx, struct sway_view *view, + float alpha) { struct render_data data = { - .damage = damage, .alpha = alpha, + .ctx = ctx, }; - output_view_for_each_popup_surface(output, view, + output_view_for_each_popup_surface(ctx->output, view, render_surface_iterator, &data); } -static void render_saved_view(struct sway_view *view, - struct sway_output *output, const pixman_region32_t *damage, float alpha) { +static void render_saved_view(struct render_context *ctx, struct sway_view *view, + float alpha) { + struct sway_output *output = ctx->output; struct wlr_output *wlr_output = output->wlr_output; if (wl_list_empty(&view->saved_buffers)) { @@ -343,7 +338,7 @@ static void render_saved_view(struct sway_view *view, } scale_box(&dst_box, wlr_output->scale); - render_texture(wlr_output, damage, saved_buf->buffer->texture, + render_texture(ctx, saved_buf->buffer->texture, &saved_buf->source_box, &dst_box, matrix, alpha); } @@ -355,13 +350,13 @@ static void render_saved_view(struct sway_view *view, /** * Render a view's surface and left/bottom/right borders. */ -static void render_view(struct sway_output *output, const pixman_region32_t *damage, +static void render_view(struct render_context *ctx, struct sway_container *con, struct border_colors *colors) { struct sway_view *view = con->view; if (!wl_list_empty(&view->saved_buffers)) { - render_saved_view(view, output, damage, view->container->alpha); + render_saved_view(ctx, view, view->container->alpha); } else if (view->surface) { - render_view_toplevels(view, output, damage, view->container->alpha); + render_view_toplevels(ctx, view, view->container->alpha); } if (con->current.border == B_NONE || con->current.border == B_CSD) { @@ -369,7 +364,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam } struct wlr_box box; - float output_scale = output->wlr_output->scale; + float output_scale = ctx->output->wlr_output->scale; float color[4]; struct sway_container_state *state = &con->current; @@ -381,7 +376,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam box.width = state->border_thickness; box.height = state->content_height; scale_box(&box, output_scale); - render_rect(output, damage, &box, color); + render_rect(ctx, &box, color); } list_t *siblings = container_get_current_siblings(con); @@ -400,7 +395,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam box.width = state->border_thickness; box.height = state->content_height; scale_box(&box, output_scale); - render_rect(output, damage, &box, color); + render_rect(ctx, &box, color); } if (state->border_bottom) { @@ -415,7 +410,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam box.width = state->width; box.height = state->border_thickness; scale_box(&box, output_scale); - render_rect(output, damage, &box, color); + render_rect(ctx, &box, color); } } @@ -428,13 +423,13 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam * The height is: 1px border, 3px padding, font height, 3px padding, 1px border * The left side is: 1px border, 2px padding, title */ -static void render_titlebar(struct sway_output *output, - const pixman_region32_t *output_damage, struct sway_container *con, +static void render_titlebar(struct render_context *ctx, struct sway_container *con, int x, int y, int width, struct border_colors *colors, struct wlr_texture *title_texture, struct wlr_texture *marks_texture) { struct wlr_box box; float color[4]; + struct sway_output *output = ctx->output; float output_scale = output->wlr_output->scale; double output_x = output->lx; double output_y = output->ly; @@ -451,7 +446,7 @@ static void render_titlebar(struct sway_output *output, box.width = width; box.height = titlebar_border_thickness; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Single pixel bar below title box.x = x; @@ -459,7 +454,7 @@ static void render_titlebar(struct sway_output *output, box.width = width; box.height = titlebar_border_thickness; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Single pixel left edge box.x = x; @@ -467,7 +462,7 @@ static void render_titlebar(struct sway_output *output, box.width = titlebar_border_thickness; box.height = container_titlebar_height() - titlebar_border_thickness * 2; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Single pixel right edge box.x = x + width - titlebar_border_thickness; @@ -475,7 +470,7 @@ static void render_titlebar(struct sway_output *output, box.width = titlebar_border_thickness; box.height = container_titlebar_height() - titlebar_border_thickness * 2; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); int inner_x = x - output_x + titlebar_h_padding; int bg_y = y + titlebar_border_thickness; @@ -524,7 +519,7 @@ static void render_titlebar(struct sway_output *output, if (ob_inner_width < texture_box.width) { texture_box.width = ob_inner_width; } - render_texture(output->wlr_output, output_damage, marks_texture, + render_texture(ctx, marks_texture, NULL, &texture_box, matrix, con->alpha); // Padding above @@ -534,12 +529,12 @@ static void render_titlebar(struct sway_output *output, box.y = roundf((y + titlebar_border_thickness) * output_scale); box.width = texture_box.width; box.height = ob_padding_above; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Padding below box.y += ob_padding_above + texture_box.height; box.height = ob_padding_below; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } // Title text @@ -600,7 +595,7 @@ static void render_titlebar(struct sway_output *output, texture_box.width = ob_inner_width - ob_marks_width; } - render_texture(output->wlr_output, output_damage, title_texture, + render_texture(ctx, title_texture, NULL, &texture_box, matrix, con->alpha); // Padding above @@ -610,12 +605,12 @@ static void render_titlebar(struct sway_output *output, box.y = roundf((y + titlebar_border_thickness) * output_scale); box.width = texture_box.width; box.height = ob_padding_above; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Padding below box.y += ob_padding_above + texture_box.height; box.height = ob_padding_below; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } // Determine the left + right extends of the textures (output-buffer local) @@ -649,7 +644,7 @@ static void render_titlebar(struct sway_output *output, box.x = ob_left_x + ob_left_width + round(output_x * output_scale); box.y = roundf(bg_y * output_scale); box.height = ob_bg_height; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } // Padding on left side @@ -663,7 +658,7 @@ static void render_titlebar(struct sway_output *output, if (box.x + box.width < left_x) { box.width += left_x - box.x - box.width; } - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Padding on right side box.x = x + width - titlebar_h_padding; @@ -677,14 +672,13 @@ static void render_titlebar(struct sway_output *output, box.width += box.x - right_rx; box.x = right_rx; } - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } /** * Render the top border line for a view using "border pixel". */ -static void render_top_border(struct sway_output *output, - const pixman_region32_t *output_damage, struct sway_container *con, +static void render_top_border(struct render_context *ctx, struct sway_container *con, struct border_colors *colors) { struct sway_container_state *state = &con->current; if (!state->border_top) { @@ -692,7 +686,7 @@ static void render_top_border(struct sway_output *output, } struct wlr_box box; float color[4]; - float output_scale = output->wlr_output->scale; + float output_scale = ctx->output->wlr_output->scale; // Child border - top edge memcpy(&color, colors->child_border, sizeof(float) * 4); @@ -702,7 +696,7 @@ static void render_top_border(struct sway_output *output, box.width = state->width; box.height = state->border_thickness; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } struct parent_data { @@ -713,8 +707,8 @@ struct parent_data { struct sway_container *active_child; }; -static void render_container(struct sway_output *output, - const pixman_region32_t *damage, struct sway_container *con, bool parent_focused); +static void render_container(struct render_context *ctx, + struct sway_container *con, bool parent_focused); /** * Render a container's children using a L_HORIZ or L_VERT layout. @@ -722,8 +716,7 @@ static void render_container(struct sway_output *output, * Wrap child views in borders and leave child containers borderless because * they'll apply their own borders to their children. */ -static void render_containers_linear(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers_linear(struct render_context *ctx, struct parent_data *parent) { for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -753,15 +746,15 @@ static void render_containers_linear(struct sway_output *output, } if (state->border == B_NORMAL) { - render_titlebar(output, damage, child, floor(state->x), + render_titlebar(ctx, child, floor(state->x), floor(state->y), state->width, colors, title_texture, marks_texture); } else if (state->border == B_PIXEL) { - render_top_border(output, damage, child, colors); + render_top_border(ctx, child, colors); } - render_view(output, damage, child, colors); + render_view(ctx, child, colors); } else { - render_container(output, damage, child, + render_container(ctx, child, parent->focused || child->current.focused); } } @@ -778,8 +771,7 @@ static bool container_has_focused_child(struct sway_container *con) { /** * Render a container's children using the L_TABBED layout. */ -static void render_containers_tabbed(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers_tabbed(struct render_context *ctx, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -827,7 +819,7 @@ static void render_containers_tabbed(struct sway_output *output, tab_width = parent->box.width - tab_width * i; } - render_titlebar(output, damage, child, x, parent->box.y, tab_width, + render_titlebar(ctx, child, x, parent->box.y, tab_width, colors, title_texture, marks_texture); if (child == current) { @@ -837,9 +829,9 @@ static void render_containers_tabbed(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - render_view(output, damage, current, current_colors); + render_view(ctx, current, current_colors); } else { - render_container(output, damage, current, + render_container(ctx, current, parent->focused || current->current.focused); } } @@ -847,8 +839,7 @@ static void render_containers_tabbed(struct sway_output *output, /** * Render a container's children using the L_STACKED layout. */ -static void render_containers_stacked(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers_stacked(struct render_context *ctx, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -890,7 +881,7 @@ static void render_containers_stacked(struct sway_output *output, } int y = parent->box.y + titlebar_height * i; - render_titlebar(output, damage, child, parent->box.x, y, + render_titlebar(ctx, child, parent->box.x, y, parent->box.width, colors, title_texture, marks_texture); if (child == current) { @@ -900,19 +891,18 @@ static void render_containers_stacked(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - render_view(output, damage, current, current_colors); + render_view(ctx, current, current_colors); } else { - render_container(output, damage, current, + render_container(ctx, current, parent->focused || current->current.focused); } } -static void render_containers(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers(struct render_context *ctx, struct parent_data *parent) { if (config->hide_lone_tab && parent->children->length == 1) { struct sway_container *child = parent->children->items[0]; if (child->view) { - render_containers_linear(output,damage, parent); + render_containers_linear(ctx, parent); return; } } @@ -921,19 +911,19 @@ static void render_containers(struct sway_output *output, case L_NONE: case L_HORIZ: case L_VERT: - render_containers_linear(output, damage, parent); + render_containers_linear(ctx, parent); break; case L_STACKED: - render_containers_stacked(output, damage, parent); + render_containers_stacked(ctx, parent); break; case L_TABBED: - render_containers_tabbed(output, damage, parent); + render_containers_tabbed(ctx, parent); break; } } -static void render_container(struct sway_output *output, - const pixman_region32_t *damage, struct sway_container *con, bool focused) { +static void render_container(struct render_context *ctx, + struct sway_container *con, bool focused) { struct parent_data data = { .layout = con->current.layout, .box = { @@ -946,11 +936,11 @@ static void render_container(struct sway_output *output, .focused = focused, .active_child = con->current.focused_inactive_child, }; - render_containers(output, damage, &data); + render_containers(ctx, &data); } -static void render_workspace(struct sway_output *output, - const pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { +static void render_workspace(struct render_context *ctx, + struct sway_workspace *ws, bool focused) { struct parent_data data = { .layout = ws->current.layout, .box = { @@ -963,11 +953,11 @@ static void render_workspace(struct sway_output *output, .focused = focused, .active_child = ws->current.focused_inactive_child, }; - render_containers(output, damage, &data); + render_containers(ctx, &data); } -static void render_floating_container(struct sway_output *soutput, - const pixman_region32_t *damage, struct sway_container *con) { +static void render_floating_container(struct render_context *ctx, + struct sway_container *con) { if (con->view) { struct sway_view *view = con->view; struct border_colors *colors; @@ -989,20 +979,19 @@ static void render_floating_container(struct sway_output *soutput, } if (con->current.border == B_NORMAL) { - render_titlebar(soutput, damage, con, floor(con->current.x), + render_titlebar(ctx, con, floor(con->current.x), floor(con->current.y), con->current.width, colors, title_texture, marks_texture); } else if (con->current.border == B_PIXEL) { - render_top_border(soutput, damage, con, colors); + render_top_border(ctx, con, colors); } - render_view(soutput, damage, con, colors); + render_view(ctx, con, colors); } else { - render_container(soutput, damage, con, con->current.focused); + render_container(ctx, con, con->current.focused); } } -static void render_floating(struct sway_output *soutput, - const pixman_region32_t *damage) { +static void render_floating(struct render_context *ctx) { for (int i = 0; i < root->outputs->length; ++i) { struct sway_output *output = root->outputs->items[i]; for (int j = 0; j < output->current.workspaces->length; ++j) { @@ -1015,23 +1004,24 @@ static void render_floating(struct sway_output *soutput, if (floater->current.fullscreen_mode != FULLSCREEN_NONE) { continue; } - render_floating_container(soutput, damage, floater); + render_floating_container(ctx, floater); } } } } -static void render_seatops(struct sway_output *output, - const pixman_region32_t *damage) { +static void render_seatops(struct render_context *ctx) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { - seatop_render(seat, output, damage); + seatop_render(seat, ctx); } } -void output_render(struct sway_output *output, pixman_region32_t *damage) { - struct wlr_output *wlr_output = output->wlr_output; - struct wlr_renderer *renderer = output->server->renderer; +void output_render(struct render_context *ctx) { + struct wlr_output *wlr_output = ctx->output->wlr_output; + struct wlr_renderer *renderer = ctx->renderer; + struct sway_output *output = ctx->output; + const pixman_region32_t *damage = ctx->output_damage; struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { @@ -1047,12 +1037,6 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { return; } - if (debug.damage == DAMAGE_RERENDER) { - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - pixman_region32_union_rect(damage, damage, 0, 0, width, height); - } - if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap goto renderer_end; @@ -1077,8 +1061,8 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { if (server.session_lock.lock != NULL) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; struct wlr_session_lock_surface_v1 *lock_surface; @@ -1113,13 +1097,12 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { if (fullscreen_con->view) { if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { - render_saved_view(fullscreen_con->view, output, damage, 1.0f); + render_saved_view(ctx, fullscreen_con->view, 1.0f); } else if (fullscreen_con->view->surface) { - render_view_toplevels(fullscreen_con->view, - output, damage, 1.0f); + render_view_toplevels(ctx, fullscreen_con->view, 1.0f); } } else { - render_container(output, damage, fullscreen_con, + render_container(ctx, fullscreen_con, fullscreen_con->current.focused); } @@ -1127,11 +1110,11 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { struct sway_container *floater = workspace->current.floating->items[i]; if (container_is_transient_for(floater, fullscreen_con)) { - render_floating_container(output, damage, floater); + render_floating_container(ctx, floater); } } #if HAVE_XWAYLAND - render_unmanaged(output, damage, &root->xwayland_unmanaged); + render_unmanaged(ctx, &root->xwayland_unmanaged); #endif } else { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; @@ -1143,41 +1126,41 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { wlr_renderer_clear(renderer, clear_color); } - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - render_workspace(output, damage, workspace, workspace->current.focused); - render_floating(output, damage); + render_workspace(ctx, workspace, workspace->current.focused); + render_floating(ctx); #if HAVE_XWAYLAND - render_unmanaged(output, damage, &root->xwayland_unmanaged); + render_unmanaged(ctx, &root->xwayland_unmanaged); #endif - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } - render_seatops(output, damage); + render_seatops(ctx); struct sway_seat *seat = input_manager_current_seat(); struct sway_container *focus = seat_get_focused_container(seat); if (focus && focus->view) { - render_view_popups(focus->view, output, damage, focus->alpha); + render_view_popups(ctx, focus->view, focus->alpha); } render_overlay: - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - render_drag_icons(output, damage, &root->drag_icons); + render_drag_icons(ctx, &root->drag_icons); renderer_end: wlr_renderer_scissor(renderer, NULL); diff --git a/sway/input/seat.c b/sway/input/seat.c index 14931ce0f2..6b95e46aa1 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1726,10 +1726,9 @@ void seatop_end(struct sway_seat *seat) { seat->seatop_impl = NULL; } -void seatop_render(struct sway_seat *seat, struct sway_output *output, - const pixman_region32_t *damage) { +void seatop_render(struct sway_seat *seat, struct render_context *ctx) { if (seat->seatop_impl->render) { - seat->seatop_impl->render(seat, output, damage); + seat->seatop_impl->render(seat, ctx); } } diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 5498e90927..26704d0d91 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -31,21 +31,20 @@ struct seatop_move_tiling_event { bool insert_after_target; }; -static void handle_render(struct sway_seat *seat, - struct sway_output *output, const pixman_region32_t *damage) { +static void handle_render(struct sway_seat *seat, struct render_context *ctx) { struct seatop_move_tiling_event *e = seat->seatop_data; if (!e->threshold_reached) { return; } - if (e->target_node && node_get_output(e->target_node) == output) { + if (e->target_node && node_get_output(e->target_node) == ctx->output) { float color[4]; memcpy(&color, config->border_colors.focused.indicator, sizeof(float) * 4); premultiply_alpha(color, 0.5); struct wlr_box box; memcpy(&box, &e->drop_box, sizeof(struct wlr_box)); - scale_box(&box, output->wlr_output->scale); - render_rect(output, damage, &box, color); + scale_box(&box, ctx->output->wlr_output->scale); + render_rect(ctx, &box, color); } } From 5ac2a9ef0ff6e61598a47e3a149fdf23efcfa7f6 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 27 Apr 2023 11:28:57 +0200 Subject: [PATCH 2/3] render: Don't pass matrix into render_texture --- sway/desktop/render.c | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f011e0ffe3..a3ae5efc2f 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -104,10 +104,18 @@ static void set_scale_filter(struct wlr_output *wlr_output, static void render_texture(struct render_context *ctx, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, - const float matrix[static 9], float alpha) { + enum wl_output_transform transform, float alpha) { struct wlr_renderer *renderer = ctx->renderer; struct sway_output *output = ctx->output; + struct wlr_box proj_box = *dst_box; + scale_box(&proj_box, output->wlr_output->scale); + + float matrix[9]; + enum wl_output_transform inv_transform = wlr_output_transform_invert(transform); + wlr_matrix_project_box(matrix, &proj_box, inv_transform, 0, + output->wlr_output->transform_matrix); + pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, @@ -152,12 +160,6 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_box proj_box = *_box; scale_box(&proj_box, wlr_output->scale); - float matrix[9]; - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &proj_box, transform, 0.0, - wlr_output->transform_matrix); - struct wlr_box dst_box = *_box; struct wlr_box *clip_box = data->clip_box; if (clip_box != NULL) { @@ -167,7 +169,7 @@ static void render_surface_iterator(struct sway_output *output, scale_box(&dst_box, wlr_output->scale); render_texture(data->ctx, texture, - &src_box, &dst_box, matrix, alpha); + &src_box, &dst_box, surface->current.transform, alpha); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); @@ -323,11 +325,6 @@ static void render_saved_view(struct render_context *ctx, struct sway_view *view struct wlr_box dst_box = proj_box; scale_box(&proj_box, wlr_output->scale); - float matrix[9]; - enum wl_output_transform transform = wlr_output_transform_invert(saved_buf->transform); - wlr_matrix_project_box(matrix, &proj_box, transform, 0, - wlr_output->transform_matrix); - if (!floating) { dst_box.width = fmin(dst_box.width, view->container->current.content_width - @@ -339,7 +336,7 @@ static void render_saved_view(struct render_context *ctx, struct sway_view *view scale_box(&dst_box, wlr_output->scale); render_texture(ctx, saved_buf->buffer->texture, - &saved_buf->source_box, &dst_box, matrix, alpha); + &saved_buf->source_box, &dst_box, saved_buf->transform, alpha); } // FIXME: we should set the surface that this saved buffer originates from @@ -511,16 +508,11 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.y = round((bg_y - output_y) * output_scale) + ob_padding_above; - float matrix[9]; - wlr_matrix_project_box(matrix, &texture_box, - WL_OUTPUT_TRANSFORM_NORMAL, - 0.0, output->wlr_output->transform_matrix); - if (ob_inner_width < texture_box.width) { texture_box.width = ob_inner_width; } render_texture(ctx, marks_texture, - NULL, &texture_box, matrix, con->alpha); + NULL, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); @@ -586,17 +578,12 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.y = round((bg_y - output_y) * output_scale) + ob_padding_above; - float matrix[9]; - wlr_matrix_project_box(matrix, &texture_box, - WL_OUTPUT_TRANSFORM_NORMAL, - 0.0, output->wlr_output->transform_matrix); - if (ob_inner_width - ob_marks_width < texture_box.width) { texture_box.width = ob_inner_width - ob_marks_width; } render_texture(ctx, title_texture, - NULL, &texture_box, matrix, con->alpha); + NULL, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); From 301e199504a9af2d7ccf7084f6ff0942c4433b53 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 2 May 2023 11:43:44 -0400 Subject: [PATCH 3/3] render: Use wlr_render_pass --- include/sway/output.h | 2 + sway/desktop/output.c | 26 ++++++- sway/desktop/render.c | 171 ++++++++++++++++++++---------------------- 3 files changed, 109 insertions(+), 90 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index b397c8e2d3..f6dc6af2bd 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -69,6 +69,8 @@ struct render_context { struct sway_output *output; struct wlr_renderer *renderer; const pixman_region32_t *output_damage; + + struct wlr_render_pass *pass; }; struct sway_output *output_create(struct wlr_output *wlr_output); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 02e08bd2d3..01bc87bbb5 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -604,9 +605,21 @@ static int output_repaint_timer_handler(void *data) { } } + if (!wlr_output_configure_primary_swapchain(wlr_output, NULL, &wlr_output->swapchain)) { + return false; + } + int buffer_age; - if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { - return 0; + struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age); + if (buffer == NULL) { + return false; + } + + struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass( + wlr_output->renderer, buffer); + if (render_pass == NULL) { + wlr_buffer_unlock(buffer); + return false; } pixman_region32_t damage; @@ -623,6 +636,7 @@ static int output_repaint_timer_handler(void *data) { .output_damage = &damage, .renderer = wlr_output->renderer, .output = output, + .pass = render_pass, }; struct timespec now; @@ -632,6 +646,14 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_fini(&damage); + if (!wlr_render_pass_submit(render_pass)) { + wlr_buffer_unlock(buffer); + return false; + } + + wlr_output_attach_buffer(wlr_output, buffer); + wlr_buffer_unlock(buffer); + if (!wlr_output_commit(wlr_output)) { return 0; } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a3ae5efc2f..37e84647ca 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -38,6 +38,23 @@ struct render_data { struct wlr_box *clip_box; }; +static void transform_output_damage(pixman_region32_t *damage, struct wlr_output *output) { + int ow, oh; + wlr_output_transformed_resolution(output, &ow, &oh); + enum wl_output_transform transform = + wlr_output_transform_invert(output->transform); + wlr_region_transform(damage, damage, transform, ow, oh); +} + +static void transform_output_box(struct wlr_box *box, struct wlr_output *output) { + int ow, oh; + wlr_output_transformed_resolution(output, &ow, &oh); + enum wl_output_transform transform = + wlr_output_transform_invert(output->transform); + wlr_box_transform(box, box, transform, ow, oh); +} + + /** * Apply scale to a width or height. * @@ -54,28 +71,6 @@ static int scale_length(int length, int offset, float scale) { return roundf((offset + length) * scale) - roundf(offset * scale); } -static void scissor_output(struct wlr_output *wlr_output, - pixman_box32_t *rect) { - struct wlr_renderer *renderer = wlr_output->renderer; - assert(renderer); - - struct wlr_box box = { - .x = rect->x1, - .y = rect->y1, - .width = rect->x2 - rect->x1, - .height = rect->y2 - rect->y1, - }; - - int ow, oh; - wlr_output_transformed_resolution(wlr_output, &ow, &oh); - - enum wl_output_transform transform = - wlr_output_transform_invert(wlr_output->transform); - wlr_box_transform(&box, &box, transform, ow, oh); - - wlr_renderer_scissor(renderer, &box); -} - static void set_scale_filter(struct wlr_output *wlr_output, struct wlr_texture *texture, enum scale_filter_mode scale_filter) { #if WLR_HAS_GLES2_RENDERER @@ -103,40 +98,39 @@ static void set_scale_filter(struct wlr_output *wlr_output, } static void render_texture(struct render_context *ctx, struct wlr_texture *texture, - const struct wlr_fbox *src_box, const struct wlr_box *dst_box, + const struct wlr_fbox *_src_box, const struct wlr_box *dst_box, enum wl_output_transform transform, float alpha) { - struct wlr_renderer *renderer = ctx->renderer; struct sway_output *output = ctx->output; struct wlr_box proj_box = *dst_box; - scale_box(&proj_box, output->wlr_output->scale); - float matrix[9]; - enum wl_output_transform inv_transform = wlr_output_transform_invert(transform); - wlr_matrix_project_box(matrix, &proj_box, inv_transform, 0, - output->wlr_output->transform_matrix); + struct wlr_fbox src_box = {0}; + if (_src_box) { + src_box = *_src_box; + } pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, - dst_box->width, dst_box->height); + pixman_region32_init_rect(&damage, proj_box.x, proj_box.y, + proj_box.width, proj_box.height); pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; } - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(output->wlr_output, &rects[i]); - set_scale_filter(output->wlr_output, texture, output->scale_filter); - if (src_box != NULL) { - wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, alpha); - } else { - wlr_render_texture_with_matrix(renderer, texture, matrix, alpha); - } - } + transform_output_box(&proj_box, output->wlr_output); + transform_output_damage(&damage, output->wlr_output); + transform = wlr_output_transform_compose(transform, output->wlr_output->transform); + + set_scale_filter(output->wlr_output, texture, output->scale_filter); + wlr_render_pass_add_texture(ctx->pass, &(struct wlr_render_texture_options) { + .texture = texture, + .src_box = src_box, + .dst_box = proj_box, + .transform = transform, + .alpha = &alpha, + .clip = &damage, + }); damage_finish: pixman_region32_fini(&damage); @@ -218,16 +212,13 @@ static void render_drag_icons(struct render_context *ctx, struct wl_list *drag_i void render_rect(struct render_context *ctx, const struct wlr_box *_box, float color[static 4]) { struct wlr_output *wlr_output = ctx->output->wlr_output; - struct wlr_renderer *renderer = ctx->renderer; - struct wlr_box box; - memcpy(&box, _box, sizeof(struct wlr_box)); + struct wlr_box box = *_box; box.x -= ctx->output->lx * wlr_output->scale; box.y -= ctx->output->ly * wlr_output->scale; pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, box.x, box.y, + pixman_region32_init_rect(&damage, box.x, box.y, box.width, box.height); pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); @@ -235,13 +226,19 @@ void render_rect(struct render_context *ctx, const struct wlr_box *_box, goto damage_finish; } - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_render_rect(renderer, &box, color, - wlr_output->transform_matrix); - } + transform_output_damage(&damage, wlr_output); + transform_output_box(&box, wlr_output); + + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = box, + .color = { + .r = color[0], + .g = color[1], + .b = color[2], + .a = color[3], + }, + .clip = &damage, + }); damage_finish: pixman_region32_fini(&damage); @@ -1006,7 +1003,6 @@ static void render_seatops(struct render_context *ctx) { void output_render(struct render_context *ctx) { struct wlr_output *wlr_output = ctx->output->wlr_output; - struct wlr_renderer *renderer = ctx->renderer; struct sway_output *output = ctx->output; const pixman_region32_t *damage = ctx->output_damage; @@ -1020,32 +1016,38 @@ void output_render(struct render_context *ctx) { fullscreen_con = workspace->current.fullscreen; } - if (!wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height)) { - return; - } - if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap goto renderer_end; } if (debug.damage == DAMAGE_HIGHLIGHT) { - wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = { .r = 1, .g = 1, .b = 0, .a = 1 }, + }); } + pixman_region32_t transformed_damage; + pixman_region32_init(&transformed_damage); + pixman_region32_copy(&transformed_damage, damage); + transform_output_damage(&transformed_damage, wlr_output); + if (server.session_lock.locked) { - float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; + struct wlr_render_color clear_color = { + .a = 1.0f + }; if (server.session_lock.lock == NULL) { // abandoned lock -> red BG - clear_color[0] = 1.f; - } - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_renderer_clear(renderer, clear_color); + clear_color.r = 1.f; } + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = clear_color, + .clip = &transformed_damage, + }); + if (server.session_lock.lock != NULL) { struct render_data data = { .alpha = 1.0f, @@ -1073,14 +1075,11 @@ void output_render(struct render_context *ctx) { } if (fullscreen_con) { - float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_renderer_clear(renderer, clear_color); - } + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = { .r = 0, .g = 0, .b = 0, .a = 1 }, + .clip = &transformed_damage, + }); if (fullscreen_con->view) { if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { @@ -1104,14 +1103,11 @@ void output_render(struct render_context *ctx) { render_unmanaged(ctx, &root->xwayland_unmanaged); #endif } else { - float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_renderer_clear(renderer, clear_color); - } + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = { .r = 0.25f, .g = 0.25f, .b = 0.25f, .a = 1 }, + .clip = &transformed_damage, + }); render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); @@ -1150,7 +1146,6 @@ void output_render(struct render_context *ctx) { render_drag_icons(ctx, &root->drag_icons); renderer_end: - wlr_renderer_scissor(renderer, NULL); - wlr_output_render_software_cursors(wlr_output, damage); - wlr_renderer_end(renderer); + pixman_region32_fini(&transformed_damage); + wlr_output_add_software_cursors_to_render_pass(wlr_output, ctx->pass, damage); }