Browse Source

- Added SDL_WINDOW_TRANSPARENT to request a window with transparent framebuffer
- Remove SDL_VIDEO_EGL_ALLOW_TRANSPARENCY hint, EGL now checks 'window->flags & SDL_WINDOW_TRANSPARENT'

Sylvain 2 years ago
parent
commit
2cafa52598

+ 0 - 11
include/SDL3/SDL_hints.h

@@ -1602,17 +1602,6 @@ extern "C" {
  */
  */
 #define SDL_HINT_VIDEO_DOUBLE_BUFFER      "SDL_VIDEO_DOUBLE_BUFFER"
 #define SDL_HINT_VIDEO_DOUBLE_BUFFER      "SDL_VIDEO_DOUBLE_BUFFER"
 
 
-/**
- * \brief A variable controlling whether the EGL window is allowed to be
- * composited as transparent, rather than opaque.
- *
- * Most window systems will always render windows opaque, even if the surface
- * format has an alpha channel. This is not always true, however, so by default
- * SDL will try to enforce opaque composition. To override this behavior, you
- * can set this hint to "1".
- */
-#define SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY "SDL_VIDEO_EGL_ALLOW_TRANSPARENCY"
-
 /**
 /**
  * \brief If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay.
  * \brief If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay.
  *
  *

+ 1 - 0
include/SDL3/SDL_video.h

@@ -152,6 +152,7 @@ typedef enum
     SDL_WINDOW_KEYBOARD_GRABBED     = 0x00100000,   /**< window has grabbed keyboard input */
     SDL_WINDOW_KEYBOARD_GRABBED     = 0x00100000,   /**< window has grabbed keyboard input */
     SDL_WINDOW_VULKAN               = 0x10000000,   /**< window usable for Vulkan surface */
     SDL_WINDOW_VULKAN               = 0x10000000,   /**< window usable for Vulkan surface */
     SDL_WINDOW_METAL                = 0x20000000,   /**< window usable for Metal view */
     SDL_WINDOW_METAL                = 0x20000000,   /**< window usable for Metal view */
+    SDL_WINDOW_TRANSPARENT          = 0x40000000,   /**< window with transparent buffer */
 
 
 } SDL_WindowFlags;
 } SDL_WindowFlags;
 
 

+ 1 - 1
src/core/android/SDL_android.c

@@ -1057,7 +1057,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, j
 
 
         /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
         /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
         if (data->egl_surface == EGL_NO_SURFACE) {
         if (data->egl_surface == EGL_NO_SURFACE) {
-            data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)data->native_window);
+            data->egl_surface = SDL_EGL_CreateSurface(_this, Android_Window, (NativeWindowType)data->native_window);
         }
         }
 
 
         /* GL Context handling is done in the event loop because this function is run from the Java thread */
         /* GL Context handling is done in the event loop because this function is run from the Java thread */

+ 6 - 1
src/test/SDL_test_common.c

@@ -33,7 +33,8 @@ static const char *video_usage[] = {
     "[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
     "[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]",
     "[--logical-scale-quality nearest|linear|best]",
     "[--logical-scale-quality nearest|linear|best]",
     "[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]",
     "[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]",
-    "[--resizable]", "[--minimize]", "[--maximize]", "[--grab]", "[--keyboard-grab]",
+    "[--resizable]", "[--transparent]",
+    "[--minimize]", "[--maximize]", "[--grab]", "[--keyboard-grab]",
     "[--hidden]", "[--input-focus]", "[--mouse-focus]",
     "[--hidden]", "[--input-focus]", "[--mouse-focus]",
     "[--flash-on-focus-loss]", "[--allow-highdpi]", "[--confine-cursor X,Y,W,H]",
     "[--flash-on-focus-loss]", "[--allow-highdpi]", "[--confine-cursor X,Y,W,H]",
     "[--usable-bounds]"
     "[--usable-bounds]"
@@ -490,6 +491,10 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
         state->window_flags |= SDL_WINDOW_RESIZABLE;
         state->window_flags |= SDL_WINDOW_RESIZABLE;
         return 1;
         return 1;
     }
     }
+    if (SDL_strcasecmp(argv[index], "--transparent") == 0) {
+        state->window_flags |= SDL_WINDOW_TRANSPARENT;
+        return 1;
+    }
     if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
     if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
         state->window_flags |= SDL_WINDOW_MINIMIZED;
         state->window_flags |= SDL_WINDOW_MINIMIZED;
         return 1;
         return 1;

+ 5 - 2
src/video/SDL_egl.c

@@ -1218,7 +1218,7 @@ int SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
 }
 }
 
 
 EGLSurface *
 EGLSurface *
-SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
+SDL_EGL_CreateSurface(_THIS, SDL_Window *window, NativeWindowType nw)
 {
 {
 #if SDL_VIDEO_DRIVER_ANDROID
 #if SDL_VIDEO_DRIVER_ANDROID
     EGLint format_wanted;
     EGLint format_wanted;
@@ -1260,7 +1260,10 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
 
 
 #ifdef EGL_EXT_present_opaque
 #ifdef EGL_EXT_present_opaque
     if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_EXT_present_opaque")) {
     if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_EXT_present_opaque")) {
-        const SDL_bool allow_transparent = SDL_GetHintBoolean(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, SDL_FALSE);
+        SDL_bool allow_transparent = SDL_FALSE;
+        if (window && (window->flags & SDL_WINDOW_TRANSPARENT)) {
+            allow_transparent = SDL_TRUE;
+        }
         attribs[attr++] = EGL_PRESENT_OPAQUE_EXT;
         attribs[attr++] = EGL_PRESENT_OPAQUE_EXT;
         attribs[attr++] = allow_transparent ? EGL_FALSE : EGL_TRUE;
         attribs[attr++] = allow_transparent ? EGL_FALSE : EGL_TRUE;
     }
     }

+ 1 - 1
src/video/SDL_egl_c.h

@@ -129,7 +129,7 @@ extern int SDL_EGL_ChooseConfig(_THIS);
 extern int SDL_EGL_SetSwapInterval(_THIS, int interval);
 extern int SDL_EGL_SetSwapInterval(_THIS, int interval);
 extern int SDL_EGL_GetSwapInterval(_THIS, int *interval);
 extern int SDL_EGL_GetSwapInterval(_THIS, int *interval);
 extern int SDL_EGL_DeleteContext(_THIS, SDL_GLContext context);
 extern int SDL_EGL_DeleteContext(_THIS, SDL_GLContext context);
-extern EGLSurface *SDL_EGL_CreateSurface(_THIS, NativeWindowType nw);
+extern EGLSurface *SDL_EGL_CreateSurface(_THIS, SDL_Window *window, NativeWindowType nw);
 extern void SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface);
 extern void SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface);
 
 
 extern EGLSurface SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height);
 extern EGLSurface SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height);

+ 4 - 3
src/video/SDL_video.c

@@ -206,6 +206,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
 {
 {
     SDL_RendererInfo info;
     SDL_RendererInfo info;
     SDL_WindowTextureData *data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
     SDL_WindowTextureData *data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
+    const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE;
     int i;
     int i;
     int w, h;
     int w, h;
 
 
@@ -274,12 +275,12 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
     SDL_free(data->pixels);
     SDL_free(data->pixels);
     data->pixels = NULL;
     data->pixels = NULL;
 
 
-    /* Find the first format without an alpha channel */
+    /* Find the first format with or without an alpha channel */
     *format = info.texture_formats[0];
     *format = info.texture_formats[0];
 
 
     for (i = 0; i < (int)info.num_texture_formats; ++i) {
     for (i = 0; i < (int)info.num_texture_formats; ++i) {
         if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
         if (!SDL_ISPIXELFORMAT_FOURCC(info.texture_formats[i]) &&
-            !SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
+            transparent == SDL_ISPIXELFORMAT_ALPHA(info.texture_formats[i])) {
             *format = info.texture_formats[i];
             *format = info.texture_formats[i];
             break;
             break;
         }
         }
@@ -1646,7 +1647,7 @@ Uint32 SDL_GetWindowPixelFormat(SDL_Window *window)
 }
 }
 
 
 #define CREATE_FLAGS \
 #define CREATE_FLAGS \
-    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL)
+    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_TRANSPARENT)
 
 
 static SDL_INLINE SDL_bool IsAcceptingDragAndDrop(void)
 static SDL_INLINE SDL_bool IsAcceptingDragAndDrop(void)
 {
 {

+ 1 - 1
src/video/android/SDL_androidwindow.c

@@ -79,7 +79,7 @@ int Android_CreateWindow(_THIS, SDL_Window *window)
        incompatible with vkCreateAndroidSurfaceKHR */
        incompatible with vkCreateAndroidSurfaceKHR */
 #if SDL_VIDEO_OPENGL_EGL
 #if SDL_VIDEO_OPENGL_EGL
     if (window->flags & SDL_WINDOW_OPENGL) {
     if (window->flags & SDL_WINDOW_OPENGL) {
-        data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)data->native_window);
+        data->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)data->native_window);
 
 
         if (data->egl_surface == EGL_NO_SURFACE) {
         if (data->egl_surface == EGL_NO_SURFACE) {
             ANativeWindow_release(data->native_window);
             ANativeWindow_release(data->native_window);

+ 2 - 1
src/video/cocoa/SDL_cocoametalview.h

@@ -43,7 +43,8 @@
 
 
 - (instancetype)initWithFrame:(NSRect)frame
 - (instancetype)initWithFrame:(NSRect)frame
                       highDPI:(BOOL)highDPI
                       highDPI:(BOOL)highDPI
-                     windowID:(Uint32)windowID;
+                     windowID:(Uint32)windowID
+                       opaque:(BOOL)opaque;
 
 
 - (void)updateDrawableSize;
 - (void)updateDrawableSize;
 - (NSView *)hitTest:(NSPoint)point;
 - (NSView *)hitTest:(NSPoint)point;

+ 7 - 2
src/video/cocoa/SDL_cocoametalview.m

@@ -76,7 +76,8 @@ static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
 
 
 - (instancetype)initWithFrame:(NSRect)frame
 - (instancetype)initWithFrame:(NSRect)frame
                       highDPI:(BOOL)highDPI
                       highDPI:(BOOL)highDPI
-                     windowID:(Uint32)windowID;
+                     windowID:(Uint32)windowID
+                       opaque:(BOOL)opaque
 {
 {
     self = [super initWithFrame:frame];
     self = [super initWithFrame:frame];
     if (self != nil) {
     if (self != nil) {
@@ -87,6 +88,8 @@ static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
         /* Allow resize. */
         /* Allow resize. */
         self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
         self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
 
 
+        self.layer.opaque = opaque;
+
         SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
         SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
 
 
         [self updateDrawableSize];
         [self updateDrawableSize];
@@ -136,13 +139,15 @@ Cocoa_Metal_CreateView(_THIS, SDL_Window *window)
         SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
         SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
         NSView *view = data.nswindow.contentView;
         NSView *view = data.nswindow.contentView;
         BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
         BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
+        BOOL opaque = (window->flags & SDL_WINDOW_TRANSPARENT) == 0;
         Uint32 windowID = SDL_GetWindowID(window);
         Uint32 windowID = SDL_GetWindowID(window);
         SDL_cocoametalview *newview;
         SDL_cocoametalview *newview;
         SDL_MetalView metalview;
         SDL_MetalView metalview;
 
 
         newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
         newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
                                                     highDPI:highDPI
                                                     highDPI:highDPI
-                                                   windowID:windowID];
+                                                   windowID:windowID
+                                                     opaque:opaque];
         if (newview == nil) {
         if (newview == nil) {
             SDL_OutOfMemory();
             SDL_OutOfMemory();
             return NULL;
             return NULL;

+ 4 - 0
src/video/cocoa/SDL_cocoaopengl.m

@@ -270,6 +270,7 @@ SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window *window)
         int glversion_minor;
         int glversion_minor;
         NSOpenGLPixelFormatAttribute profile;
         NSOpenGLPixelFormatAttribute profile;
         int interval;
         int interval;
+        int opaque;
 
 
         if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
         if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
 #if SDL_VIDEO_OPENGL_EGL
 #if SDL_VIDEO_OPENGL_EGL
@@ -381,6 +382,9 @@ SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window *window)
         interval = 0;
         interval = 0;
         [context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
         [context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
 
 
+        opaque = (window->flags & SDL_WINDOW_TRANSPARENT) ? 0 : 1;
+        [context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
+
         if (Cocoa_GL_MakeCurrent(_this, window, sdlcontext) < 0) {
         if (Cocoa_GL_MakeCurrent(_this, window, sdlcontext) < 0) {
             SDL_GL_DeleteContext(sdlcontext);
             SDL_GL_DeleteContext(sdlcontext);
             SDL_SetError("Failed making OpenGL context current");
             SDL_SetError("Failed making OpenGL context current");

+ 1 - 1
src/video/cocoa/SDL_cocoaopengles.m

@@ -137,7 +137,7 @@ int Cocoa_GLES_SetupWindow(_THIS, SDL_Window *window)
 
 
         /* Create the GLES window surface */
         /* Create the GLES window surface */
         v = windowdata.nswindow.contentView;
         v = windowdata.nswindow.contentView;
-        windowdata.egl_surface = SDL_EGL_CreateSurface(_this, (__bridge NativeWindowType)[v layer]);
+        windowdata.egl_surface = SDL_EGL_CreateSurface(_this, window, (__bridge NativeWindowType)[v layer]);
 
 
         if (windowdata.egl_surface == EGL_NO_SURFACE) {
         if (windowdata.egl_surface == EGL_NO_SURFACE) {
             return SDL_SetError("Could not create GLES window surface");
             return SDL_SetError("Could not create GLES window surface");

+ 20 - 3
src/video/cocoa/SDL_cocoawindow.m

@@ -1600,11 +1600,14 @@ static int Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL_
     /* Force the graphics context to clear to black so we don't get a flash of
     /* Force the graphics context to clear to black so we don't get a flash of
        white until the app is ready to draw. In practice on modern macOS, this
        white until the app is ready to draw. In practice on modern macOS, this
        only gets called for window creation and other extraordinary events. */
        only gets called for window creation and other extraordinary events. */
+    BOOL transparent = (_sdlWindow->flags & SDL_WINDOW_TRANSPARENT) != 0;
     if ([NSGraphicsContext currentContext]) {
     if ([NSGraphicsContext currentContext]) {
-        [[NSColor blackColor] setFill];
+        NSColor *fillColor = transparent ? [NSColor clearColor] : [NSColor blackColor];
+        [fillColor setFill];
         NSRectFill(dirtyRect);
         NSRectFill(dirtyRect);
     } else if (self.layer) {
     } else if (self.layer) {
-        self.layer.backgroundColor = CGColorGetConstantColor(kCGColorBlack);
+        CFStringRef color = transparent ? kCGColorClear : kCGColorBlack;
+        self.layer.backgroundColor = CGColorGetConstantColor(color);
     }
     }
 
 
     SDL_SendWindowEvent(_sdlWindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
     SDL_SendWindowEvent(_sdlWindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
@@ -1621,7 +1624,9 @@ static int Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL_
     /* Force the graphics context to clear to black so we don't get a flash of
     /* Force the graphics context to clear to black so we don't get a flash of
        white until the app is ready to draw. In practice on modern macOS, this
        white until the app is ready to draw. In practice on modern macOS, this
        only gets called for window creation and other extraordinary events. */
        only gets called for window creation and other extraordinary events. */
-    self.layer.backgroundColor = CGColorGetConstantColor(kCGColorBlack);
+    BOOL transparent = (_sdlWindow->flags & SDL_WINDOW_TRANSPARENT) != 0;
+    CFStringRef color = transparent ? kCGColorClear : kCGColorBlack;
+    self.layer.backgroundColor = CGColorGetConstantColor(color);
     ScheduleContextUpdates((__bridge SDL_CocoaWindowData *)_sdlWindow->driverdata);
     ScheduleContextUpdates((__bridge SDL_CocoaWindowData *)_sdlWindow->driverdata);
     SDL_SendWindowEvent(_sdlWindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
     SDL_SendWindowEvent(_sdlWindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
 }
 }
@@ -1744,6 +1749,12 @@ static int SetupWindowData(_THIS, SDL_Window *window, NSWindow *nswindow, NSView
             }
             }
         }
         }
 
 
+        if (nswindow.isOpaque) {
+            window->flags &= ~SDL_WINDOW_TRANSPARENT;
+        } else {
+            window->flags |= SDL_WINDOW_TRANSPARENT;
+        }
+
         /* SDL_CocoaWindowData will be holding a strong reference to the NSWindow, and
         /* SDL_CocoaWindowData will be holding a strong reference to the NSWindow, and
          * it will also call [NSWindow close] in DestroyWindow before releasing the
          * it will also call [NSWindow close] in DestroyWindow before releasing the
          * NSWindow, so the extra release provided by releasedWhenClosed isn't
          * NSWindow, so the extra release provided by releasedWhenClosed isn't
@@ -1841,6 +1852,12 @@ int Cocoa_CreateWindow(_THIS, SDL_Window *window)
             [nswindow setLevel:NSFloatingWindowLevel];
             [nswindow setLevel:NSFloatingWindowLevel];
         }
         }
 
 
+        if (window->flags & SDL_WINDOW_TRANSPARENT) {
+            nswindow.opaque = NO;
+            nswindow.hasShadow = NO;
+            nswindow.backgroundColor = [NSColor clearColor];
+        }
+
         /* Create a default view for this window */
         /* Create a default view for this window */
         rect = [nswindow contentRectForFrameRect:[nswindow frame]];
         rect = [nswindow contentRectForFrameRect:[nswindow frame]];
         contentView = [[SDLView alloc] initWithFrame:rect];
         contentView = [[SDLView alloc] initWithFrame:rect];

+ 1 - 1
src/video/kmsdrm/SDL_kmsdrmvideo.c

@@ -1198,7 +1198,7 @@ int KMSDRM_CreateSurfaces(_THIS, SDL_Window *window)
        but we need an EGL surface NOW, or GL won't be able to render into any surface
        but we need an EGL surface NOW, or GL won't be able to render into any surface
        and we won't see the first frame. */
        and we won't see the first frame. */
     SDL_EGL_SetRequiredVisualId(_this, surface_fmt);
     SDL_EGL_SetRequiredVisualId(_this, surface_fmt);
-    windata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)windata->gs);
+    windata->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)windata->gs);
 
 
     if (windata->egl_surface == EGL_NO_SURFACE) {
     if (windata->egl_surface == EGL_NO_SURFACE) {
         ret = SDL_SetError("Could not create EGL window surface");
         ret = SDL_SetError("Could not create EGL window surface");

+ 1 - 1
src/video/raspberry/SDL_rpivideo.c

@@ -287,7 +287,7 @@ int RPI_CreateWindow(_THIS, SDL_Window *window)
             return -1;
             return -1;
         }
         }
     }
     }
-    wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)&wdata->dispman_window);
+    wdata->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)&wdata->dispman_window);
 
 
     if (wdata->egl_surface == EGL_NO_SURFACE) {
     if (wdata->egl_surface == EGL_NO_SURFACE) {
         return SDL_SetError("Could not create GLES window surface");
         return SDL_SetError("Could not create GLES window surface");

+ 1 - 1
src/video/vita/SDL_vitavideo.c

@@ -275,7 +275,7 @@ int VITA_CreateWindow(_THIS, SDL_Window *window)
             _this->gl_config.minor_version = 1;
             _this->gl_config.minor_version = 1;
             _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
             _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
         }
         }
-        wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
+        wdata->egl_surface = SDL_EGL_CreateSurface(_this, window, &win);
         if (wdata->egl_surface == EGL_NO_SURFACE) {
         if (wdata->egl_surface == EGL_NO_SURFACE) {
             return SDL_SetError("Could not create GLES window surface");
             return SDL_SetError("Could not create GLES window surface");
         }
         }

+ 1 - 1
src/video/vivante/SDL_vivantevideo.c

@@ -267,7 +267,7 @@ int VIVANTE_CreateWindow(_THIS, SDL_Window *window)
 
 
 #if SDL_VIDEO_OPENGL_EGL
 #if SDL_VIDEO_OPENGL_EGL
     if (window->flags & SDL_WINDOW_OPENGL) {
     if (window->flags & SDL_WINDOW_OPENGL) {
-        data->egl_surface = SDL_EGL_CreateSurface(_this, data->native_window);
+        data->egl_surface = SDL_EGL_CreateSurface(_this, window, data->native_window);
         if (data->egl_surface == EGL_NO_SURFACE) {
         if (data->egl_surface == EGL_NO_SURFACE) {
             return SDL_SetError("VIVANTE: Can't create EGL surface");
             return SDL_SetError("VIVANTE: Can't create EGL surface");
         }
         }

+ 0 - 2
src/video/wayland/SDL_waylandvideo.c

@@ -948,7 +948,6 @@ int Wayland_VideoInit(_THIS)
     WAYLAND_wl_display_flush(data->display);
     WAYLAND_wl_display_flush(data->display);
 
 
     Wayland_InitKeyboard(_this);
     Wayland_InitKeyboard(_this);
-    Wayland_InitWin(data);
 
 
     data->initializing = SDL_FALSE;
     data->initializing = SDL_FALSE;
 
 
@@ -981,7 +980,6 @@ static void Wayland_VideoCleanup(_THIS)
     SDL_VideoData *data = _this->driverdata;
     SDL_VideoData *data = _this->driverdata;
     int i, j;
     int i, j;
 
 
-    Wayland_QuitWin(data);
     Wayland_FiniMouse(data);
     Wayland_FiniMouse(data);
 
 
     for (i = _this->num_displays - 1; i >= 0; --i) {
     for (i = _this->num_displays - 1; i >= 0; --i) {

+ 0 - 1
src/video/wayland/SDL_waylandvideo.h

@@ -97,7 +97,6 @@ struct SDL_VideoData
     char *classname;
     char *classname;
 
 
     int relative_mouse_mode;
     int relative_mouse_mode;
-    SDL_bool egl_transparency_enabled;
 };
 };
 
 
 struct SDL_DisplayData
 struct SDL_DisplayData

+ 8 - 41
src/video/wayland/SDL_waylandwindow.c

@@ -224,7 +224,7 @@ static void ConfigureWindowGeometry(SDL_Window *window)
             xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height);
             xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height);
         }
         }
 
 
-        if (!viddata->egl_transparency_enabled) {
+        if (!(window->flags & SDL_WINDOW_TRANSPARENT)) {
             region = wl_compositor_create_region(viddata->compositor);
             region = wl_compositor_create_region(viddata->compositor);
             wl_region_add(region, 0, 0,
             wl_region_add(region, 0, 0,
                           data->wl_window_width, data->wl_window_height);
                           data->wl_window_width, data->wl_window_height);
@@ -2010,12 +2010,18 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
     }
     }
 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
 
 
+    if (window->flags & SDL_WINDOW_TRANSPARENT) {
+        if (_this->gl_config.alpha_size == 0) {
+            _this->gl_config.alpha_size = 8;
+        }
+    }
+
     if (window->flags & SDL_WINDOW_OPENGL) {
     if (window->flags & SDL_WINDOW_OPENGL) {
         data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height);
         data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height);
 
 
 #if SDL_VIDEO_OPENGL_EGL
 #if SDL_VIDEO_OPENGL_EGL
         /* Create the GLES window surface */
         /* Create the GLES window surface */
-        data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)data->egl_window);
+        data->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)data->egl_window);
 
 
         if (data->egl_surface == EGL_NO_SURFACE) {
         if (data->egl_surface == EGL_NO_SURFACE) {
             return -1; /* SDL_EGL_CreateSurface should have set error */
             return -1; /* SDL_EGL_CreateSurface should have set error */
@@ -2247,43 +2253,4 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
     window->driverdata = NULL;
     window->driverdata = NULL;
 }
 }
 
 
-static void EGLTransparencyChangedCallback(void *userdata, const char *name, const char *oldValue, const char *newValue)
-{
-    const SDL_bool oldval = SDL_GetStringBoolean(oldValue, SDL_FALSE);
-    const SDL_bool newval = SDL_GetStringBoolean(newValue, SDL_FALSE);
-
-    if (oldval != newval) {
-        SDL_Window *window;
-        SDL_VideoData *viddata = (SDL_VideoData *)userdata;
-        SDL_VideoDevice *dev = SDL_GetVideoDevice();
-
-        viddata->egl_transparency_enabled = newval;
-
-        /* Iterate over all windows and update the surface opaque regions */
-        for (window = dev->windows; window != NULL; window = window->next) {
-            SDL_WindowData *wind = window->driverdata;
-
-            if (!newval) {
-                struct wl_region *region = wl_compositor_create_region(wind->waylandData->compositor);
-                wl_region_add(region, 0, 0, wind->wl_window_width, wind->wl_window_height);
-                wl_surface_set_opaque_region(wind->surface, region);
-                wl_region_destroy(region);
-            } else {
-                wl_surface_set_opaque_region(wind->surface, NULL);
-            }
-        }
-    }
-}
-
-void Wayland_InitWin(SDL_VideoData *data)
-{
-    data->egl_transparency_enabled = SDL_GetHintBoolean(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, SDL_FALSE);
-    SDL_AddHintCallback(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, EGLTransparencyChangedCallback, data);
-}
-
-void Wayland_QuitWin(SDL_VideoData *data)
-{
-    SDL_DelHintCallback(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, EGLTransparencyChangedCallback, data);
-}
-
 #endif /* SDL_VIDEO_DRIVER_WAYLAND */
 #endif /* SDL_VIDEO_DRIVER_WAYLAND */

+ 0 - 3
src/video/wayland/SDL_waylandwindow.h

@@ -155,7 +155,4 @@ extern int Wayland_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *inf
 extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
 extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
 extern int Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation);
 extern int Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation);
 
 
-extern void Wayland_InitWin(SDL_VideoData *data);
-extern void Wayland_QuitWin(SDL_VideoData *data);
-
 #endif /* SDL_waylandwindow_h_ */
 #endif /* SDL_waylandwindow_h_ */

+ 1 - 1
src/video/windows/SDL_windowsopengles.c

@@ -125,7 +125,7 @@ int WIN_GLES_SetupWindow(_THIS, SDL_Window *window)
     }
     }
 
 
     /* Create the GLES window surface */
     /* Create the GLES window surface */
-    windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)windowdata->hwnd);
+    windowdata->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)windowdata->hwnd);
 
 
     if (windowdata->egl_surface == EGL_NO_SURFACE) {
     if (windowdata->egl_surface == EGL_NO_SURFACE) {
         return SDL_SetError("Could not create GLES window surface");
         return SDL_SetError("Could not create GLES window surface");

+ 34 - 14
src/video/x11/SDL_x11opengl.c

@@ -345,7 +345,7 @@ static void X11_GL_InitExtensions(_THIS)
     const char *(*glXQueryExtensionsStringFunc)(Display *, int);
     const char *(*glXQueryExtensionsStringFunc)(Display *, int);
     const char *extensions;
     const char *extensions;
 
 
-    vinfo = X11_GL_GetVisual(_this, display, screen);
+    vinfo = X11_GL_GetVisual(_this, display, screen, SDL_FALSE);
     if (vinfo) {
     if (vinfo) {
         GLXContext (*glXGetCurrentContextFunc)(void) =
         GLXContext (*glXGetCurrentContextFunc)(void) =
             (GLXContext(*)(void))
             (GLXContext(*)(void))
@@ -484,7 +484,7 @@ static void X11_GL_InitExtensions(_THIS)
  *  In case of failure, if that pointer is not NULL, set that pointer to None
  *  In case of failure, if that pointer is not NULL, set that pointer to None
  *  and try again.
  *  and try again.
  */
  */
-static int X11_GL_GetAttributes(_THIS, Display *display, int screen, int *attribs, int size, Bool for_FBConfig, int **_pvistypeattr)
+static int X11_GL_GetAttributes(_THIS, Display *display, int screen, int *attribs, int size, Bool for_FBConfig, int **_pvistypeattr, SDL_bool transparent)
 {
 {
     int i = 0;
     int i = 0;
     const int MAX_ATTRIBUTES = 64;
     const int MAX_ATTRIBUTES = 64;
@@ -583,13 +583,15 @@ static int X11_GL_GetAttributes(_THIS, Display *display, int screen, int *attrib
         attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT : GLX_SLOW_VISUAL_EXT;
         attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT : GLX_SLOW_VISUAL_EXT;
     }
     }
 
 
-    /* If we're supposed to use DirectColor visuals, and we've got the
-       EXT_visual_info extension, then add GLX_X_VISUAL_TYPE_EXT. */
-    if (X11_UseDirectColorVisuals() &&
-        _this->gl_data->HAS_GLX_EXT_visual_info) {
-        pvistypeattr = &attribs[i];
-        attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
-        attribs[i++] = GLX_DIRECT_COLOR_EXT;
+    /* Un-wanted when we request a transparent buffer */
+    if (!transparent) {
+        /* If we're supposed to use DirectColor visuals, and we've got the
+           EXT_visual_info extension, then add GLX_X_VISUAL_TYPE_EXT. */
+        if (X11_UseDirectColorVisuals() && _this->gl_data->HAS_GLX_EXT_visual_info) {
+            pvistypeattr = &attribs[i];
+            attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
+            attribs[i++] = GLX_DIRECT_COLOR_EXT;
+        }
     }
     }
 
 
     attribs[i++] = None;
     attribs[i++] = None;
@@ -603,7 +605,7 @@ static int X11_GL_GetAttributes(_THIS, Display *display, int screen, int *attrib
     return i;
     return i;
 }
 }
 
 
-XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen)
+XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen, SDL_bool transparent)
 {
 {
     /* 64 seems nice. */
     /* 64 seems nice. */
     int attribs[64];
     int attribs[64];
@@ -620,13 +622,30 @@ XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen)
         GLXFBConfig *framebuffer_config = NULL;
         GLXFBConfig *framebuffer_config = NULL;
         int fbcount = 0;
         int fbcount = 0;
 
 
-        X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_TRUE, &pvistypeattr);
+        X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_TRUE, &pvistypeattr, transparent);
         framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount);
         framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount);
         if (!framebuffer_config && (pvistypeattr != NULL)) {
         if (!framebuffer_config && (pvistypeattr != NULL)) {
             *pvistypeattr = None;
             *pvistypeattr = None;
             framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount);
             framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount);
         }
         }
 
 
+        if (transparent) {
+            /* Return the first transparent Visual */
+            int i;
+            for (i = 0; i < fbcount; i++) {
+                Uint32 format;
+                vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[i]);
+                format = X11_GetPixelFormatFromVisualInfo(display, vinfo);
+                if (SDL_ISPIXELFORMAT_ALPHA(format)) { /* found! */
+                    X11_XFree(framebuffer_config);
+                    framebuffer_config = NULL;
+                    break;
+                }
+                X11_XFree(vinfo);
+                vinfo = NULL;
+            }
+        }
+
         if (framebuffer_config) {
         if (framebuffer_config) {
             vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[0]);
             vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[0]);
         }
         }
@@ -635,7 +654,7 @@ XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen)
     }
     }
 
 
     if (!vinfo) {
     if (!vinfo) {
-        X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE, &pvistypeattr);
+        X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE, &pvistypeattr, transparent);
         vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
         vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
 
 
         if (!vinfo && (pvistypeattr != NULL)) {
         if (!vinfo && (pvistypeattr != NULL)) {
@@ -696,6 +715,7 @@ SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window)
     XVisualInfo v, *vinfo;
     XVisualInfo v, *vinfo;
     int n;
     int n;
     GLXContext context = NULL, share_context;
     GLXContext context = NULL, share_context;
+    const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE;
 
 
     if (_this->gl_config.share_with_current_context) {
     if (_this->gl_config.share_with_current_context) {
         share_context = (GLXContext)SDL_GL_GetCurrentContext();
         share_context = (GLXContext)SDL_GL_GetCurrentContext();
@@ -716,7 +736,7 @@ SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window)
     if (vinfo) {
     if (vinfo) {
         if (_this->gl_config.major_version < 3 &&
         if (_this->gl_config.major_version < 3 &&
             _this->gl_config.profile_mask == 0 &&
             _this->gl_config.profile_mask == 0 &&
-            _this->gl_config.flags == 0) {
+            _this->gl_config.flags == 0 && !transparent) {
             /* Create legacy context */
             /* Create legacy context */
             context =
             context =
                 _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
                 _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
@@ -776,7 +796,7 @@ SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window)
                 int fbcount = 0;
                 int fbcount = 0;
                 int *pvistypeattr = NULL;
                 int *pvistypeattr = NULL;
 
 
-                X11_GL_GetAttributes(_this, display, screen, glxAttribs, 64, SDL_TRUE, &pvistypeattr);
+                X11_GL_GetAttributes(_this, display, screen, glxAttribs, 64, SDL_TRUE, &pvistypeattr, transparent);
 
 
                 if (_this->gl_data->glXChooseFBConfig) {
                 if (_this->gl_data->glXChooseFBConfig) {
                     framebuffer_config = _this->gl_data->glXChooseFBConfig(display,
                     framebuffer_config = _this->gl_data->glXChooseFBConfig(display,

+ 1 - 1
src/video/x11/SDL_x11opengl.h

@@ -72,7 +72,7 @@ extern int X11_GL_LoadLibrary(_THIS, const char *path);
 extern SDL_FunctionPointer X11_GL_GetProcAddress(_THIS, const char *proc);
 extern SDL_FunctionPointer X11_GL_GetProcAddress(_THIS, const char *proc);
 extern void X11_GL_UnloadLibrary(_THIS);
 extern void X11_GL_UnloadLibrary(_THIS);
 extern SDL_bool X11_GL_UseEGL(_THIS);
 extern SDL_bool X11_GL_UseEGL(_THIS);
-extern XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen);
+extern XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen, SDL_bool transparent);
 extern SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window);
 extern SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window);
 extern int X11_GL_MakeCurrent(_THIS, SDL_Window *window,
 extern int X11_GL_MakeCurrent(_THIS, SDL_Window *window,
                               SDL_GLContext context);
                               SDL_GLContext context);

+ 18 - 1
src/video/x11/SDL_x11opengles.c

@@ -56,7 +56,7 @@ int X11_GLES_LoadLibrary(_THIS, const char *path)
 }
 }
 
 
 XVisualInfo *
 XVisualInfo *
-X11_GLES_GetVisual(_THIS, Display *display, int screen)
+X11_GLES_GetVisual(_THIS, Display *display, int screen, SDL_bool transparent)
 {
 {
 
 
     XVisualInfo *egl_visualinfo = NULL;
     XVisualInfo *egl_visualinfo = NULL;
@@ -79,6 +79,23 @@ X11_GLES_GetVisual(_THIS, Display *display, int screen)
         egl_visualinfo = X11_XGetVisualInfo(display,
         egl_visualinfo = X11_XGetVisualInfo(display,
                                             VisualScreenMask,
                                             VisualScreenMask,
                                             &vi_in, &out_count);
                                             &vi_in, &out_count);
+
+        /* Return the first transparent Visual */
+        if (transparent) {
+            int i;
+            for (i = 0; i < out_count; i++) {
+                XVisualInfo *v = &egl_visualinfo[i];
+                Uint32 format = X11_GetPixelFormatFromVisualInfo(display, v);
+                if (SDL_ISPIXELFORMAT_ALPHA(format)) { /* found! */
+                    /* re-request it to have a copy that can be X11_XFree'ed later */
+                    vi_in.screen = screen;
+                    vi_in.visualid = v->visualid;
+                    X11_XFree(egl_visualinfo);
+                    egl_visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count);
+                    return egl_visualinfo;
+                }
+            }
+        }
     } else {
     } else {
         vi_in.screen = screen;
         vi_in.screen = screen;
         vi_in.visualid = visual_id;
         vi_in.visualid = visual_id;

+ 1 - 1
src/video/x11/SDL_x11opengles.h

@@ -44,7 +44,7 @@ typedef struct SDL_PrivateGLESData
 #define X11_GLES_DeleteContext   SDL_EGL_DeleteContext
 #define X11_GLES_DeleteContext   SDL_EGL_DeleteContext
 
 
 extern int X11_GLES_LoadLibrary(_THIS, const char *path);
 extern int X11_GLES_LoadLibrary(_THIS, const char *path);
-extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display *display, int screen);
+extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display *display, int screen, SDL_bool transparent);
 extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window *window);
 extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window *window);
 extern int X11_GLES_SwapWindow(_THIS, SDL_Window *window);
 extern int X11_GLES_SwapWindow(_THIS, SDL_Window *window);
 extern int X11_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context);
 extern int X11_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context);

+ 4 - 3
src/video/x11/SDL_x11window.c

@@ -431,6 +431,7 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
     SDL_WindowData *windowdata;
     SDL_WindowData *windowdata;
     Display *display = data->display;
     Display *display = data->display;
     int screen = displaydata->screen;
     int screen = displaydata->screen;
+    const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE;
     Visual *visual;
     Visual *visual;
     int depth;
     int depth;
     XSetWindowAttributes xattr;
     XSetWindowAttributes xattr;
@@ -477,12 +478,12 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
             && (!_this->gl_data || X11_GL_UseEGL(_this))
             && (!_this->gl_data || X11_GL_UseEGL(_this))
 #endif
 #endif
         ) {
         ) {
-            vinfo = X11_GLES_GetVisual(_this, display, screen);
+            vinfo = X11_GLES_GetVisual(_this, display, screen, transparent);
         } else
         } else
 #endif
 #endif
         {
         {
 #if SDL_VIDEO_OPENGL_GLX
 #if SDL_VIDEO_OPENGL_GLX
-            vinfo = X11_GL_GetVisual(_this, display, screen);
+            vinfo = X11_GL_GetVisual(_this, display, screen, transparent);
 #endif
 #endif
         }
         }
 
 
@@ -720,7 +721,7 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
         }
         }
 
 
         /* Create the GLES window surface */
         /* Create the GLES window surface */
-        windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)w);
+        windowdata->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)w);
 
 
         if (windowdata->egl_surface == EGL_NO_SURFACE) {
         if (windowdata->egl_surface == EGL_NO_SURFACE) {
             return SDL_SetError("Could not create GLES window surface");
             return SDL_SetError("Could not create GLES window surface");

+ 1 - 1
test/testgl.c

@@ -92,7 +92,7 @@ static void Render(void)
     };
     };
 
 
     /* Do our drawing, too. */
     /* Do our drawing, too. */
-    ctx.glClearColor(0.0, 0.0, 0.0, 1.0);
+    ctx.glClearColor(0.0, 0.0, 0.0, 0.0 /* used with --transparent */);
     ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
 
     ctx.glBegin(GL_QUADS);
     ctx.glBegin(GL_QUADS);

+ 1 - 1
test/testsprite.c

@@ -126,7 +126,7 @@ static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
     }
     }
 
 
     /* Draw a gray background */
     /* Draw a gray background */
-    SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
+    SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0x00 /* used with --transparent */);
     SDL_RenderClear(renderer);
     SDL_RenderClear(renderer);
 
 
     /* Test points */
     /* Test points */

+ 10 - 2
test/testvulkan.c

@@ -624,6 +624,7 @@ static SDL_bool createSwapchain(void)
     int w, h;
     int w, h;
     VkSwapchainCreateInfoKHR createInfo = { 0 };
     VkSwapchainCreateInfoKHR createInfo = { 0 };
     VkResult result;
     VkResult result;
+    Uint32 flags;
 
 
     // pick an image count
     // pick an image count
     vulkanContext->swapchainDesiredImageCount = vulkanContext->surfaceCapabilities.minImageCount + 1;
     vulkanContext->swapchainDesiredImageCount = vulkanContext->surfaceCapabilities.minImageCount + 1;
@@ -651,6 +652,9 @@ static SDL_bool createSwapchain(void)
     // get size
     // get size
     SDL_GetWindowSizeInPixels(vulkanContext->window, &w, &h);
     SDL_GetWindowSizeInPixels(vulkanContext->window, &w, &h);
 
 
+    // get flags
+    flags = SDL_GetWindowFlags(vulkanContext->window);
+
     // Clamp the size to the allowable image extent.
     // Clamp the size to the allowable image extent.
     // SDL_GetWindowSizeInPixels()'s result it not always in this range (bug #3287)
     // SDL_GetWindowSizeInPixels()'s result it not always in this range (bug #3287)
     vulkanContext->swapchainSize.width = SDL_clamp((uint32_t)w,
     vulkanContext->swapchainSize.width = SDL_clamp((uint32_t)w,
@@ -677,7 +681,11 @@ static SDL_bool createSwapchain(void)
     createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
     createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
     createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
     createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
     createInfo.preTransform = vulkanContext->surfaceCapabilities.currentTransform;
     createInfo.preTransform = vulkanContext->surfaceCapabilities.currentTransform;
-    createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+    if (flags & SDL_WINDOW_TRANSPARENT) {
+        createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
+    } else {
+        createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+    }
     createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
     createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
     createInfo.clipped = VK_TRUE;
     createInfo.clipped = VK_TRUE;
     createInfo.oldSwapchain = vulkanContext->swapchain;
     createInfo.oldSwapchain = vulkanContext->swapchain;
@@ -1037,7 +1045,7 @@ static SDL_bool render(void)
     clearColor.float32[0] = (float)(0.5 + 0.5 * SDL_sin(currentTime));
     clearColor.float32[0] = (float)(0.5 + 0.5 * SDL_sin(currentTime));
     clearColor.float32[1] = (float)(0.5 + 0.5 * SDL_sin(currentTime + SDL_PI_D * 2 / 3));
     clearColor.float32[1] = (float)(0.5 + 0.5 * SDL_sin(currentTime + SDL_PI_D * 2 / 3));
     clearColor.float32[2] = (float)(0.5 + 0.5 * SDL_sin(currentTime + SDL_PI_D * 4 / 3));
     clearColor.float32[2] = (float)(0.5 + 0.5 * SDL_sin(currentTime + SDL_PI_D * 4 / 3));
-    clearColor.float32[3] = 1;
+    clearColor.float32[3] = 0.5; // for SDL_WINDOW_TRANSPARENT, ignored with VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
     rerecordCommandBuffer(frameIndex, &clearColor);
     rerecordCommandBuffer(frameIndex, &clearColor);
     submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     submitInfo.waitSemaphoreCount = 1;
     submitInfo.waitSemaphoreCount = 1;