Merge branch 'cursor_chill' into 'master'

output: limit rate of hardware cursor texture change

See merge request wlroots/wlroots!5309
This commit is contained in:
Félix Poisot 2026-04-11 11:19:26 +00:00
commit 291eff46b8
4 changed files with 22 additions and 1 deletions

View file

@ -17,6 +17,7 @@ bool output_pick_format(struct wlr_output *output,
bool output_ensure_buffer(struct wlr_output *output,
struct wlr_output_state *state, bool *new_back_buffer);
bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor);
bool output_cursor_set_texture(struct wlr_output_cursor *cursor,
struct wlr_texture *texture, bool own_texture, const struct wlr_fbox *src_box,
int dst_width, int dst_height, enum wl_output_transform transform,

View file

@ -278,6 +278,8 @@ struct wlr_output {
struct wlr_output_image_description image_description_value;
struct wlr_color_transform *color_transform;
struct wlr_color_primaries default_primaries_value;
int cursor_uploaded_this_frame;
struct wlr_output_cursor *cursor_pending_upload;
} WLR_PRIVATE;
};

View file

@ -14,6 +14,11 @@
#include "types/wlr_buffer.h"
#include "types/wlr_output.h"
// Maximum of hardware cursor renders per frame.
// Many clients don't regroup the buffer commit and the hotspot change in a
// single message : typical burst of 2 must still be processed without delay
#define MAX_UPLOADS_PER_FRAME 2
static bool output_set_hardware_cursor(struct wlr_output *output,
struct wlr_buffer *buffer, int hotspot_x, int hotspot_y) {
if (!output->impl->set_cursor) {
@ -55,6 +60,7 @@ static void output_disable_hardware_cursor(struct wlr_output *output) {
output_set_hardware_cursor(output, NULL, 0, 0);
output_cursor_damage_whole(output->hardware_cursor);
output->hardware_cursor = NULL;
output->cursor_pending_upload = NULL;
}
void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock) {
@ -288,7 +294,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
return buffer;
}
static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
struct wlr_output *output = cursor->output;
if (!output->impl->set_cursor || output->software_cursor_locks > 0) {
@ -297,6 +303,11 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
struct wlr_texture *texture = cursor->texture;
if (texture != NULL && output->cursor_uploaded_this_frame >= MAX_UPLOADS_PER_FRAME) {
output->cursor_pending_upload = cursor;
return true;
}
// If the cursor was hidden or was a software cursor, the hardware
// cursor position is outdated
output_move_hardware_cursor(cursor->output, (int)cursor->x, (int)cursor->y);
@ -308,6 +319,7 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
wlr_log(WLR_DEBUG, "Failed to render cursor buffer");
return false;
}
output->cursor_uploaded_this_frame++;
}
struct wlr_box hotspot = {

View file

@ -841,6 +841,12 @@ bool wlr_output_commit_state(struct wlr_output *output,
wlr_buffer_unlock(pending.buffer);
}
output->cursor_uploaded_this_frame = 0;
if (output->cursor_pending_upload) {
output_cursor_attempt_hardware(output->cursor_pending_upload);
output->cursor_pending_upload = NULL;
}
return true;
}