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.
This commit is contained in:
Frank Praznik
2025-10-20 19:00:29 -04:00
parent 544772173f
commit 7c110cb0f1
2 changed files with 30 additions and 3 deletions

View File

@@ -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. // Wayland requires premultiplied alpha for its surfaces.
SDL_PremultiplyAlpha(surface->w, surface->h, SDL_PremultiplyAlpha(surface->w, surface->h,
surface->format, surface->pixels, surface->pitch, surface->format, surface->pixels, surface->pitch,

View File

@@ -2995,16 +2995,31 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa
for (int i = 0; i < image_count; ++i) { for (int i = 0; i < image_count; ++i) {
if (images[i]->w == images[i]->h) { if (images[i]->w == images[i]->h) {
SDL_Surface *surface = images[i];
Wayland_SHMBuffer *buffer = &wind->icon_buffers[wind->icon_buffer_count]; 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"); SDL_SetError("wayland: failed to allocate SHM buffer for the icon");
goto failure_cleanup; 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); if (surface->format != SDL_PIXELFORMAT_ARGB8888) {
const int scale = (int)SDL_ceil((double)images[i]->w / (double)icon->w); 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); 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++; wind->icon_buffer_count++;
} else { } 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); 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);