From e0321ca5b6cb70ce178e533884b407571d2d1002 Mon Sep 17 00:00:00 2001
From: rhett-lee <[EMAIL REDACTED]>
Date: Sun, 20 Oct 2024 11:21:50 +0800
Subject: [PATCH] SDL3: SDL_render_gl(render name: opengl) dose not support
transparent on Linux/X11 (Bug #11273) (#11274)
SDL3: SDL_render_gl(render name: opengl) dose not support transparent on Linux/X11:
Create SDL window with SDL_WINDOW_TRANSPARENT flag;
Create "opengl" renderer for the window;
The window can't shown with errors:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor opcode of failed request: 3 (X_ShmPutImage)
Bug reason:
SDL_x11window.c:490 : bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
SDL_x11window.c:566 : vinfo = X11_GL_GetVisual(_this, display, screen, transparent);[XVisualInfo *vinfo]
the X11_GL_GetVisual function returns a vinfo dose not support transparent.
Fix:
SDL_x11opengl.c:637 : XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent)
X11_GL_GetVisual should returns a vinfo support transparent when transparent is true.
---
src/video/x11/SDL_x11opengl.c | 58 +++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c
index 7eb6f467e043d..888c4892421c7 100644
--- a/src/video/x11/SDL_x11opengl.c
+++ b/src/video/x11/SDL_x11opengl.c
@@ -608,6 +608,32 @@ static int X11_GL_GetAttributes(SDL_VideoDevice *_this, Display *display, int sc
return i;
}
+//get the first transparent Visual
+static XVisualInfo* X11_GL_GetTransparentVisualInfo(Display *display, int screen)
+{
+ XVisualInfo* visualinfo = NULL;
+ XVisualInfo vi_in;
+ int out_count = 0;
+
+ vi_in.screen = screen;
+ visualinfo = X11_XGetVisualInfo(display, VisualScreenMask, &vi_in, &out_count);
+ if (visualinfo != NULL) {
+ int i = 0;
+ for (i = 0; i < out_count; i++) {
+ XVisualInfo* v = &visualinfo[i];
+ Uint32 format = X11_GetPixelFormatFromVisualInfo(display, v);
+ if (SDL_ISPIXELFORMAT_ALPHA(format)) {
+ vi_in.screen = screen;
+ vi_in.visualid = v->visualid;
+ X11_XFree(visualinfo);
+ visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count);
+ break;
+ }
+ }
+ }
+ return visualinfo;
+}
+
XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent)
{
// 64 seems nice.
@@ -666,6 +692,18 @@ XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int scre
}
}
+ if (transparent && vinfo) {
+ Uint32 format = X11_GetPixelFormatFromVisualInfo(display, vinfo);
+ if (!SDL_ISPIXELFORMAT_ALPHA(format)) {
+ // not transparent!
+ XVisualInfo* visualinfo = X11_GL_GetTransparentVisualInfo(display, screen);
+ if (visualinfo != NULL) {
+ X11_XFree(vinfo);
+ vinfo = visualinfo;
+ }
+ }
+ }
+
if (!vinfo) {
SDL_SetError("Couldn't find matching GLX visual");
}
@@ -814,6 +852,26 @@ SDL_GLContext X11_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
&fbcount);
}
+ if (transparent && (framebuffer_config != NULL)) {
+ int i;
+ for (i = 0; i < fbcount; i++) {
+ XVisualInfo* vinfo_temp = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[i]);
+ if ( vinfo_temp != NULL) {
+ Uint32 format = X11_GetPixelFormatFromVisualInfo(display, vinfo_temp);
+ if (SDL_ISPIXELFORMAT_ALPHA(format)) {
+ // found!
+ context = (SDL_GLContext)_this->gl_data->glXCreateContextAttribsARB(display,
+ framebuffer_config[i],
+ share_context, True, attribs);
+ X11_XFree(framebuffer_config);
+ framebuffer_config = NULL;
+ X11_XFree(vinfo_temp);
+ break;
+ }
+ X11_XFree(vinfo_temp);
+ }
+ }
+ }
if (framebuffer_config) {
context = (SDL_GLContext)_this->gl_data->glXCreateContextAttribsARB(display,
framebuffer_config[0],