SDL: wayland: Convert alternate images to ARGB8888

From 7c110cb0f17b621ec332359f6672d11f6c93dd86 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Mon, 20 Oct 2025 19:00:29 -0400
Subject: [PATCH] wayland: Convert alternate images to ARGB8888

The higher-level functions only convert the base image, so alternate scaled images for icons and cursors need to be converted when being copied to the buffers.
---
 src/video/wayland/SDL_waylandmouse.c  | 12 ++++++++++++
 src/video/wayland/SDL_waylandwindow.c | 21 ++++++++++++++++++---
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c
index 6bfb0079b81d8..b40058cbe7865 100644
--- a/src/video/wayland/SDL_waylandmouse.c
+++ b/src/video/wayland/SDL_waylandmouse.c
@@ -552,6 +552,18 @@ static Wayland_ScaledCustomCursor *Wayland_CacheScaledCustomCursor(SDL_CursorDat
                 }
             }
 
+            if (surface->format != SDL_PIXELFORMAT_ARGB8888) {
+                SDL_Surface *temp = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888);
+                if (temp) {
+                    SDL_DestroySurface(surface);
+                    surface = temp;
+                } else {
+                    Wayland_ReleaseSHMPool(cache->shmPool);
+                    SDL_free(cache);
+                    return NULL;
+                }
+            }
+
             // Wayland requires premultiplied alpha for its surfaces.
             SDL_PremultiplyAlpha(surface->w, surface->h,
                                  surface->format, surface->pixels, surface->pitch,
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 46337c89e12c5..2e8b65bb0c672 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -2995,16 +2995,31 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa
 
     for (int i = 0; i < image_count; ++i) {
         if (images[i]->w == images[i]->h) {
+            SDL_Surface *surface = images[i];
             Wayland_SHMBuffer *buffer = &wind->icon_buffers[wind->icon_buffer_count];
 
-            if (!Wayland_AllocSHMBuffer(images[i]->w, images[i]->h, buffer)) {
+            if (!Wayland_AllocSHMBuffer(surface->w, surface->h, buffer)) {
                 SDL_SetError("wayland: failed to allocate SHM buffer for the icon");
                 goto failure_cleanup;
             }
 
-            SDL_PremultiplyAlpha(images[i]->w, images[i]->h, images[i]->format, images[i]->pixels, images[i]->pitch, SDL_PIXELFORMAT_ARGB8888, buffer->shm_data, images[i]->w * 4, true);
-            const int scale = (int)SDL_ceil((double)images[i]->w / (double)icon->w);
+            if (surface->format != SDL_PIXELFORMAT_ARGB8888) {
+                surface = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888);
+                if (!surface) {
+                    goto failure_cleanup;
+                }
+            }
+
+            SDL_PremultiplyAlpha(surface->w, surface->h, surface->format, surface->pixels, surface->pitch, SDL_PIXELFORMAT_ARGB8888, buffer->shm_data, surface->w * 4, true);
+
+            const int scale = (int)SDL_ceil((double)surface->w / (double)icon->w);
             xdg_toplevel_icon_v1_add_buffer(wind->xdg_toplevel_icon_v1, buffer->wl_buffer, scale);
+
+            // Clean up the temporary conversion surface.
+            if (surface != images[i]) {
+                SDL_DestroySurface(surface);
+            }
+
             wind->icon_buffer_count++;
         } else {
             SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "wayland: icon width and height must be equal, got %ix%i for image level %i; skipping", images[i]->w, images[i]->h, i);