From 2cafa525981b1ec2fe25ced632221d639ec11f96 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Sat, 11 Mar 2023 13:53:14 +0100
Subject: [PATCH] - 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'
---
include/SDL3/SDL_hints.h | 11 ------
include/SDL3/SDL_video.h | 1 +
src/core/android/SDL_android.c | 2 +-
src/test/SDL_test_common.c | 7 +++-
src/video/SDL_egl.c | 7 +++-
src/video/SDL_egl_c.h | 2 +-
src/video/SDL_video.c | 7 ++--
src/video/android/SDL_androidwindow.c | 2 +-
src/video/cocoa/SDL_cocoametalview.h | 3 +-
src/video/cocoa/SDL_cocoametalview.m | 9 ++++-
src/video/cocoa/SDL_cocoaopengl.m | 4 ++
src/video/cocoa/SDL_cocoaopengles.m | 2 +-
src/video/cocoa/SDL_cocoawindow.m | 23 ++++++++++--
src/video/kmsdrm/SDL_kmsdrmvideo.c | 2 +-
src/video/raspberry/SDL_rpivideo.c | 2 +-
src/video/vita/SDL_vitavideo.c | 2 +-
src/video/vivante/SDL_vivantevideo.c | 2 +-
src/video/wayland/SDL_waylandvideo.c | 2 -
src/video/wayland/SDL_waylandvideo.h | 1 -
src/video/wayland/SDL_waylandwindow.c | 49 ++++---------------------
src/video/wayland/SDL_waylandwindow.h | 3 --
src/video/windows/SDL_windowsopengles.c | 2 +-
src/video/x11/SDL_x11opengl.c | 48 +++++++++++++++++-------
src/video/x11/SDL_x11opengl.h | 2 +-
src/video/x11/SDL_x11opengles.c | 19 +++++++++-
src/video/x11/SDL_x11opengles.h | 2 +-
src/video/x11/SDL_x11window.c | 7 ++--
test/testgl.c | 2 +-
test/testsprite.c | 2 +-
test/testvulkan.c | 12 +++++-
30 files changed, 136 insertions(+), 103 deletions(-)
diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h
index 552d59234d3d..1d2bf9b53a9d 100644
--- a/include/SDL3/SDL_hints.h
+++ b/include/SDL3/SDL_hints.h
@@ -1602,17 +1602,6 @@ extern "C" {
*/
#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.
*
diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h
index b0f6dbd629b3..be728962571a 100644
--- a/include/SDL3/SDL_video.h
+++ b/include/SDL3/SDL_video.h
@@ -152,6 +152,7 @@ typedef enum
SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */
SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */
+ SDL_WINDOW_TRANSPARENT = 0x40000000, /**< window with transparent buffer */
} SDL_WindowFlags;
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 20f8b35c47e0..8a927fc22dbf 100644
--- a/src/core/android/SDL_android.c
+++ b/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 (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 */
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index 69fa3300338b..b90e05ea0f48 100644
--- a/src/test/SDL_test_common.c
+++ b/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-scale-quality nearest|linear|best]",
"[--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]",
"[--flash-on-focus-loss]", "[--allow-highdpi]", "[--confine-cursor X,Y,W,H]",
"[--usable-bounds]"
@@ -490,6 +491,10 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
state->window_flags |= SDL_WINDOW_RESIZABLE;
return 1;
}
+ if (SDL_strcasecmp(argv[index], "--transparent") == 0) {
+ state->window_flags |= SDL_WINDOW_TRANSPARENT;
+ return 1;
+ }
if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
state->window_flags |= SDL_WINDOW_MINIMIZED;
return 1;
diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c
index ea9a1d372a2d..857dbce177d0 100644
--- a/src/video/SDL_egl.c
+++ b/src/video/SDL_egl.c
@@ -1218,7 +1218,7 @@ int SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
}
EGLSurface *
-SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
+SDL_EGL_CreateSurface(_THIS, SDL_Window *window, NativeWindowType nw)
{
#if SDL_VIDEO_DRIVER_ANDROID
EGLint format_wanted;
@@ -1260,7 +1260,10 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
#ifdef 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++] = allow_transparent ? EGL_FALSE : EGL_TRUE;
}
diff --git a/src/video/SDL_egl_c.h b/src/video/SDL_egl_c.h
index e177b8fd8967..603b21663768 100644
--- a/src/video/SDL_egl_c.h
+++ b/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_GetSwapInterval(_THIS, int *interval);
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 EGLSurface SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 762eb7746685..fa3ffe68aca0 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -206,6 +206,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
{
SDL_RendererInfo info;
SDL_WindowTextureData *data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA);
+ const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? SDL_TRUE : SDL_FALSE;
int i;
int w, h;
@@ -274,12 +275,12 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
SDL_free(data->pixels);
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];
for (i = 0; i < (int)info.num_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];
break;
}
@@ -1646,7 +1647,7 @@ Uint32 SDL_GetWindowPixelFormat(SDL_Window *window)
}
#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)
{
diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c
index c932c34c503b..6abc585a7b11 100644
--- a/src/video/android/SDL_androidwindow.c
+++ b/src/video/android/SDL_androidwindow.c
@@ -79,7 +79,7 @@ int Android_CreateWindow(_THIS, SDL_Window *window)
incompatible with vkCreateAndroidSurfaceKHR */
#if SDL_VIDEO_OPENGL_EGL
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) {
ANativeWindow_release(data->native_window);
diff --git a/src/video/cocoa/SDL_cocoametalview.h b/src/video/cocoa/SDL_cocoametalview.h
index d53fc30f9ec8..2712dadd6498 100644
--- a/src/video/cocoa/SDL_cocoametalview.h
+++ b/src/video/cocoa/SDL_cocoametalview.h
@@ -43,7 +43,8 @@
- (instancetype)initWithFrame:(NSRect)frame
highDPI:(BOOL)highDPI
- windowID:(Uint32)windowID;
+ windowID:(Uint32)windowID
+ opaque:(BOOL)opaque;
- (void)updateDrawableSize;
- (NSView *)hitTest:(NSPoint)point;
diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m
index 71509aec511d..d2e3e2ec6252 100644
--- a/src/video/cocoa/SDL_cocoametalview.m
+++ b/src/video/cocoa/SDL_cocoametalview.m
@@ -76,7 +76,8 @@ - (CALayer *)makeBackingLayer
- (instancetype)initWithFrame:(NSRect)frame
highDPI:(BOOL)highDPI
- windowID:(Uint32)windowID;
+ windowID:(Uint32)windowID
+ opaque:(BOOL)opaque
{
self = [super initWithFrame:frame];
if (self != nil) {
@@ -87,6 +88,8 @@ - (instancetype)initWithFrame:(NSRect)frame
/* Allow resize. */
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
+ self.layer.opaque = opaque;
+
SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
[self updateDrawableSize];
@@ -136,13 +139,15 @@ - (NSView *)hitTest:(NSPoint)point
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
NSView *view = data.nswindow.contentView;
BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
+ BOOL opaque = (window->flags & SDL_WINDOW_TRANSPARENT) == 0;
Uint32 windowID = SDL_GetWindowID(window);
SDL_cocoametalview *newview;
SDL_MetalView metalview;
newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
highDPI:highDPI
- windowID:windowID];
+ windowID:windowID
+ opaque:opaque];
if (newview == nil) {
SDL_OutOfMemory();
return NULL;
diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m
index 553cfaf62344..175dffb16009 100644
--- a/src/video/cocoa/SDL_cocoaopengl.m
+++ b/src/video/cocoa/SDL_cocoaopengl.m
@@ -270,6 +270,7 @@ SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window *window)
int glversion_minor;
NSOpenGLPixelFormatAttribute profile;
int interval;
+ int opaque;
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
#if SDL_VIDEO_OPENGL_EGL
@@ -381,6 +382,9 @@ SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window *window)
interval = 0;
[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) {
SDL_GL_DeleteContext(sdlcontext);
SDL_SetError("Failed making OpenGL context current");
diff --git a/src/video/cocoa/SDL_cocoaopengles.m b/src/video/cocoa/SDL_cocoaopengles.m
index 46c0f66c68ff..8206fe66bedd 100644
--- a/src/video/cocoa/SDL_cocoaopengles.m
+++ b/src/video/cocoa/SDL_cocoaopengles.m
@@ -137,7 +137,7 @@ int Cocoa_GLES_SetupWindow(_THIS, SDL_Window *window)
/* Create the GLES window surface */
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) {
return SDL_SetError("Could not create GLES window surface");
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 02fd42096ccd..c1d4c5946bcd 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -1600,11 +1600,14 @@ - (void)drawRect:(NSRect)dirtyRect
/* 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
only gets called for window creation and other extraordinary events. */
+ BOOL transparent = (_sdlWindow->flags & SDL_WINDOW_TRANSPARENT) != 0;
if ([NSGraphicsContext currentContext]) {
- [[NSColor blackColor] setFill];
+ NSColor *fillColor = transparent ? [NSColor clearColor] : [NSColor blackColor];
+ [fillColor setFill];
NSRectFill(dirtyRect);
} 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);
@@ -1621,7 +1624,9 @@ - (void)updateLayer
/* 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
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);
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
* it will also call [NSWindow close] in DestroyWindow before releasing the
* NSWindow, so the extra release provided by releasedWhenClosed isn't
@@ -1841,6 +1852,12 @@ int Cocoa_CreateWindow(_THIS, SDL_Window *window)
[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 */
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
contentView = [[SDLView alloc] initWithFrame:rect];
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index 24b66e92e00c..d8ac3f583207 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/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
and we won't see the first frame. */
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) {
ret = SDL_SetError("Could not create EGL window surface");
diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c
index 6c4af7d09282..e9a584799987 100644
--- a/src/video/raspberry/SDL_rpivideo.c
+++ b/src/video/raspberry/SDL_rpivideo.c
@@ -287,7 +287,7 @@ int RPI_CreateWindow(_THIS, SDL_Window *window)
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) {
return SDL_SetError("Could not create GLES window surface");
diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c
index 6712e2cde0e6..05e647cf3ef6 100644
--- a/src/video/vita/SDL_vitavideo.c
+++ b/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.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) {
return SDL_SetError("Could not create GLES window surface");
}
diff --git a/src/video/vivante/SDL_vivantevideo.c b/src/video/vivante/SDL_vivantevideo.c
index ccf5b4e6f85e..41da76ebfad9 100644
--- a/src/video/vivante/SDL_vivantevideo.c
+++ b/src/video/vivante/SDL_vivantevideo.c
@@ -267,7 +267,7 @@ int VIVANTE_CreateWindow(_THIS, SDL_Window *window)
#if SDL_VIDEO_OPENGL_EGL
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) {
return SDL_SetError("VIVANTE: Can't create EGL surface");
}
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index aa4ec89a0678..1f42324e0a56 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -948,7 +948,6 @@ int Wayland_VideoInit(_THIS)
WAYLAND_wl_display_flush(data->display);
Wayland_InitKeyboard(_this);
- Wayland_InitWin(data);
data->initializing = SDL_FALSE;
@@ -981,7 +980,6 @@ static void Wayland_VideoCleanup(_THIS)
SDL_VideoData *data = _this->driverdata;
int i, j;
- Wayland_QuitWin(data);
Wayland_FiniMouse(data);
for (i = _this->num_displays - 1; i >= 0; --i) {
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index 12530ad491fa..46fd82dc9f17 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -97,7 +97,6 @@ struct SDL_VideoData
char *classname;
int relative_mouse_mode;
- SDL_bool egl_transparency_enabled;
};
struct SDL_DisplayData
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 46f5891a5e90..70ef278b43b9 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/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);
}
- if (!viddata->egl_transparency_enabled) {
+ if (!(window->flags & SDL_WINDOW_TRANSPARENT)) {
region = wl_compositor_create_region(viddata->compositor);
wl_region_add(region, 0, 0,
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 */
+ 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) {
data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height);
#if SDL_VIDEO_OPENGL_EGL
/* 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) {
return -1; /* SDL_EGL_CreateSurface should have set error */
@@ -2247,43 +2253,4 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
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 */
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 16271056bfa9..7d17be72a9fb 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/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_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_ */
diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c
index c05b53b15f88..7d181954042c 100644
--- a/src/video/windows/SDL_windowsopengles.c
+++ b/src/video/windows/SDL_windowsopengles.c
@@ -125,7 +125,7 @@ int WIN_GLES_SetupWindow(_THIS, SDL_Window *window)
}
/* 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) {
return SDL_SetError("Could not create GLES window surface");
diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c
index 0c09a8c70107..8f35b0cab317 100644
--- a/src/video/x11/SDL_x11opengl.c
+++ b/src/video/x11/SDL_x11opengl.c
@@ -345,7 +345,7 @@ static void X11_GL_InitExtensions(_THIS)
const char *(*glXQueryExtensionsStringFunc)(Display *, int);
const char *extensions;
- vinfo = X11_GL_GetVisual(_this, display, screen);
+ vinfo = X11_GL_GetVisual(_this, display, screen, SDL_FALSE);
if (vinfo) {
GLXContext (*glXGetCurrentContextFunc)(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
* 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;
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;
}
- /* 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;
@@ -603,7 +605,7 @@ static int X11_GL_GetAttributes(_THIS, Display *display, int screen, int *attrib
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. */
int attribs[64];
@@ -620,13 +622,30 @@ XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen)
GLXFBConfig *framebuffer_config = NULL;
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);
if (!framebuffer_config && (pvistypeattr != NULL)) {
*pvistypeattr = None;
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) {
vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[0]);
}
@@ -635,7 +654,7 @@ XVisualInfo *X11_GL_GetVisual(_THIS, Display *display, int screen)
}
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);
if (!vinfo && (pvistypeattr != NULL)) {
@@ -696,6 +715,7 @@ SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window)
XVisualInfo v, *vinfo;
int n;
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) {
share_context = (GLXContext)SDL_GL_GetCurrentContext();
@@ -716,7 +736,7 @@ SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window)
if (vinfo) {
if (_this->gl_config.major_version < 3 &&
_this->gl_config.profile_mask == 0 &&
- _this->gl_config.flags == 0) {
+ _this->gl_config.flags == 0 && !transparent) {
/* Create legacy context */
context =
_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 *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) {
framebuffer_config = _this->gl_data->glXChooseFBConfig(display,
diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h
index af6c13664826..08569739a77b 100644
--- a/src/video/x11/SDL_x11opengl.h
+++ b/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 void X11_GL_UnloadLibrary(_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_GLContex
(Patch may be truncated, please check the link at the top of this post.)