Skip to content

Commit 3a59163

Browse files
committed
wayland: Optimize custom cursor image lookup
Store the images in order from smallest to largest to simplify lookup and be able to early-out of the search loop even if there is no exact match for the scale.
1 parent 6a510d6 commit 3a59163

File tree

2 files changed

+15
-18
lines changed

2 files changed

+15
-18
lines changed

src/video/wayland/SDL_waylandevents_c.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ typedef struct SDL_WaylandSeat
126126
struct wl_list link;
127127

128128
Uint32 last_implicit_grab_serial; // The serial of the last implicit grab event for window activation and selection data.
129-
Uint32 registry_id; // The ID of the Wayland seat object,
129+
Uint32 registry_id; // The ID of the Wayland seat object,
130130

131131
struct
132132
{

src/video/wayland/SDL_waylandmouse.c

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -309,23 +309,11 @@ static struct wl_buffer *Wayland_CursorStateGetFrame(SDL_WaylandCursorState *sta
309309
* desired size are preferred over images that are smaller.
310310
*/
311311
CustomCursorImage *closest = NULL;
312-
int desired_w = (int)SDL_round(data->cursor_data.custom.width * state->scale);
313-
int desired_h = (int)SDL_round(data->cursor_data.custom.height * state->scale);
314-
int desired_size = desired_w * desired_h;
315-
int closest_distance = -1;
316-
int closest_size = -1;
317-
for (int i = 0; i < data->cursor_data.custom.images_per_frame && closest_distance && data->cursor_data.custom.images[offset + i].buffer; ++i) {
318-
CustomCursorImage *candidate = &data->cursor_data.custom.images[offset + i];
319-
int size = candidate->width * candidate->height;
320-
int delta_w = candidate->width - desired_w;
321-
int delta_h = candidate->height - desired_h;
322-
int distance = (delta_w * delta_w) + (delta_h * delta_h);
323-
if (closest_distance < 0 || distance < closest_distance ||
324-
(size > desired_size && closest_size < desired_size)) {
325-
closest = candidate;
326-
closest_distance = distance;
327-
closest_size = size;
328-
}
312+
const int target_area = SDL_lround(data->cursor_data.custom.width * data->cursor_data.custom.height * state->scale);
313+
int closest_area = 0;
314+
for (int i = 0; i < data->cursor_data.custom.images_per_frame && closest_area < target_area && data->cursor_data.custom.images[offset + i].buffer; ++i) {
315+
closest = &data->cursor_data.custom.images[offset + i];
316+
closest_area = closest->width * closest->height;
329317
}
330318

331319
return closest ? closest->buffer : NULL;
@@ -732,6 +720,14 @@ static bool Wayland_GetSystemCursor(SDL_CursorData *cdata, SDL_WaylandCursorStat
732720
return true;
733721
}
734722

723+
static int surface_sort_callback(const void *a, const void *b)
724+
{
725+
SDL_Surface *s1 = (SDL_Surface *)a;
726+
SDL_Surface *s2 = (SDL_Surface *)b;
727+
728+
return (s1->w * s1->h) <= (s2->w * s2->h) ? -1 : 1;
729+
}
730+
735731
static SDL_Cursor *Wayland_CreateAnimatedCursor(SDL_CursorFrameInfo *frames, int frame_count, int hot_x, int hot_y)
736732
{
737733
SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor));
@@ -760,6 +756,7 @@ static SDL_Cursor *Wayland_CreateAnimatedCursor(SDL_CursorFrameInfo *frames, int
760756
goto failed;
761757
}
762758

759+
SDL_qsort(surfaces[i].surfaces, surfaces[i].count, sizeof(SDL_Surface *), surface_sort_callback);
763760
max_images = SDL_max(max_images, surfaces[i].count);
764761
for (int j = 0; j < surfaces[i].count; ++j) {
765762
pool_size += surfaces[i].surfaces[j]->w * surfaces[i].surfaces[j]->h * 4;

0 commit comments

Comments
 (0)