From e0321ca5b6cb70ce178e533884b407571d2d1002 Mon Sep 17 00:00:00 2001 From: rhett-lee <118450286+rhett-lee@users.noreply.github.com> 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 7eb6f467e0..888c489242 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],