SDL: wayland: Wayland cursors should use premultiplied alpha

From b528d48446c8c9c005ad122dddfdb2b46ad4553a Mon Sep 17 00:00:00 2001
From: David Gow <[EMAIL REDACTED]>
Date: Fri, 22 Oct 2021 16:59:46 +0800
Subject: [PATCH] wayland: Wayland cursors should use premultiplied alpha

It turns out that Wayland's WL_SHM_FORMAT_ARGB8888 format (and, indeed,
all wayland RGBA formats) should be treated as premultiplied. SDL
surfaces tend not to be premultiplied, and this is assumed by other
backends when dealing with cursors.

This change premultiplies the cursor surface in Wayland_CreateCursor()
using the new SDL_PremultiplySurfaceAlphaToARGB8888(). In so doing, it
also adds support for a wider range of input surfaces, including those
with non-ARGB8888 pixel formats, and those which don't have
pitch==width.

This should fix #4856
---
 src/video/wayland/SDL_waylandmouse.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c
index 5de1d45db5..19a439f695 100644
--- a/src/video/wayland/SDL_waylandmouse.c
+++ b/src/video/wayland/SDL_waylandmouse.c
@@ -34,6 +34,7 @@
 #include "SDL_mouse.h"
 #include "../../events/SDL_mouse_c.h"
 #include "SDL_waylandvideo.h"
+#include "../SDL_pixels_c.h"
 #include "SDL_waylandevents_c.h"
 
 #include "wayland-cursor.h"
@@ -267,10 +268,6 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
         }
         cursor->driverdata = (void *) data;
 
-        /* Assume ARGB8888 */
-        SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
-        SDL_assert(surface->pitch == surface->w * 4);
-
         /* Allocate shared memory buffer for this cursor */
         if (create_buffer_from_shm (data,
                                     surface->w,
@@ -282,9 +279,8 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
             return NULL;
         }
 
-        SDL_memcpy(data->shm_data,
-                   surface->pixels,
-                   surface->h * surface->pitch);
+        /* Wayland requires premultiplied alpha for its surfaces. */
+        SDL_PremultiplySurfaceAlphaToARGB8888(surface, data->shm_data);
 
         data->surface = wl_compositor_create_surface(wd->compositor);
         wl_surface_set_user_data(data->surface, NULL);