diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 767418bd..dbf7524a 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -112,6 +112,7 @@ struct wlr_output_state { }; struct wlr_output_impl; +struct wlr_render_pass; /** * A compositor output region. This typically corresponds to a monitor that @@ -515,6 +516,13 @@ void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock); */ void wlr_output_render_software_cursors(struct wlr_output *output, const pixman_region32_t *damage); +/** + * Render software cursors. + * + * This is a utility function that can be called when compositors render. + */ +void wlr_output_add_software_cursors_to_render_pass(struct wlr_output *output, + struct wlr_render_pass *render_pass, const pixman_region32_t *damage); /** * Get the set of DRM formats suitable for the primary buffer, assuming a * buffer with the specified capabilities. diff --git a/types/output/cursor.c b/types/output/cursor.c index 6ab557b5..d83e3244 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "render/allocator/allocator.h" #include "types/wlr_buffer.h" #include "types/wlr_output.h" @@ -156,6 +157,61 @@ void wlr_output_render_software_cursors(struct wlr_output *output, pixman_region32_fini(&render_damage); } +void wlr_output_add_software_cursors_to_render_pass(struct wlr_output *output, + struct wlr_render_pass *render_pass, const pixman_region32_t *damage) { + int width, height; + wlr_output_transformed_resolution(output, &width, &height); + + pixman_region32_t render_damage; + pixman_region32_init_rect(&render_damage, 0, 0, width, height); + if (damage != NULL) { + pixman_region32_intersect(&render_damage, &render_damage, damage); + } + + struct wlr_output_cursor *cursor; + wl_list_for_each(cursor, &output->cursors, link) { + if (!cursor->enabled || !cursor->visible || + output->hardware_cursor == cursor) { + continue; + } + + struct wlr_texture *texture = cursor->texture; + if (cursor->surface != NULL) { + texture = wlr_surface_get_texture(cursor->surface); + } + if (texture == NULL) { + continue; + } + + struct wlr_box box; + output_cursor_get_box(cursor, &box); + + pixman_region32_t cursor_damage; + pixman_region32_init_rect(&cursor_damage, box.x, box.y, box.width, box.height); + pixman_region32_intersect(&cursor_damage, &cursor_damage, &render_damage); + if (!pixman_region32_not_empty(&cursor_damage)) { + pixman_region32_fini(&cursor_damage); + continue; + } + + enum wl_output_transform transform = + wlr_output_transform_invert(output->transform); + wlr_box_transform(&box, &box, transform, width, height); + wlr_region_transform(&cursor_damage, &cursor_damage, transform, width, height); + + wlr_render_pass_add_texture(render_pass, &(struct wlr_render_texture_options) { + .texture = texture, + .dst_box = box, + .clip = &cursor_damage, + .transform = output->transform, + }); + + pixman_region32_fini(&cursor_damage); + } + + pixman_region32_fini(&render_damage); +} + static void output_cursor_damage_whole(struct wlr_output_cursor *cursor) { struct wlr_box box; output_cursor_get_box(cursor, &box);