- 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'
main
Sylvain 2023-03-11 13:53:14 +01:00 committed by Sylvain Becker
parent 4dededd345
commit 2cafa52598
30 changed files with 136 additions and 103 deletions

View File

@ -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.
*

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -76,7 +76,8 @@ static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
- (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 @@ static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
/* Allow resize. */
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
self.layer.opaque = opaque;
SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
[self updateDrawableSize];
@ -136,13 +139,15 @@ Cocoa_Metal_CreateView(_THIS, SDL_Window *window)
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;

View File

@ -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");

View File

@ -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");

View File

@ -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
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 @@ 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
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];

View File

@ -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");

View File

@ -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");

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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) {

View File

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

View File

@ -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 */

View File

@ -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_ */

View File

@ -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");

View File

@ -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,

View File

@ -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_GLContext X11_GL_CreateContext(_THIS, SDL_Window *window);
extern int X11_GL_MakeCurrent(_THIS, SDL_Window *window,
SDL_GLContext context);

View File

@ -56,7 +56,7 @@ int X11_GLES_LoadLibrary(_THIS, const char *path)
}
XVisualInfo *
X11_GLES_GetVisual(_THIS, Display *display, int screen)
X11_GLES_GetVisual(_THIS, Display *display, int screen, SDL_bool transparent)
{
XVisualInfo *egl_visualinfo = NULL;
@ -79,6 +79,23 @@ X11_GLES_GetVisual(_THIS, Display *display, int screen)
egl_visualinfo = X11_XGetVisualInfo(display,
VisualScreenMask,
&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 {
vi_in.screen = screen;
vi_in.visualid = visual_id;

View File

@ -44,7 +44,7 @@ typedef struct SDL_PrivateGLESData
#define X11_GLES_DeleteContext SDL_EGL_DeleteContext
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 int X11_GLES_SwapWindow(_THIS, SDL_Window *window);
extern int X11_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context);

View File

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

View File

@ -92,7 +92,7 @@ static void Render(void)
};
/* 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.glBegin(GL_QUADS);

View File

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

View File

@ -624,6 +624,7 @@ static SDL_bool createSwapchain(void)
int w, h;
VkSwapchainCreateInfoKHR createInfo = { 0 };
VkResult result;
Uint32 flags;
// pick an image count
vulkanContext->swapchainDesiredImageCount = vulkanContext->surfaceCapabilities.minImageCount + 1;
@ -651,6 +652,9 @@ static SDL_bool createSwapchain(void)
// get size
SDL_GetWindowSizeInPixels(vulkanContext->window, &w, &h);
// get flags
flags = SDL_GetWindowFlags(vulkanContext->window);
// Clamp the size to the allowable image extent.
// SDL_GetWindowSizeInPixels()'s result it not always in this range (bug #3287)
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.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
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.clipped = VK_TRUE;
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[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[3] = 1;
clearColor.float32[3] = 0.5; // for SDL_WINDOW_TRANSPARENT, ignored with VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
rerecordCommandBuffer(frameIndex, &clearColor);
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;