[KMS/DRM][Vulkan] Fix segfault when changing fullscren mode and permanent cursor when changing between Vulkan and GL renderers in vkQuake3. Tidy up window destruction code.

This commit is contained in:
Manuel Alfayate Corchete 2020-12-27 00:43:06 +01:00
parent e7c479414b
commit 46d31d570d
2 changed files with 31 additions and 20 deletions

View File

@ -822,6 +822,8 @@ KMSDRM_CreateDevice(int devindex)
viddata->devindex = devindex; viddata->devindex = devindex;
viddata->drm_fd = -1; viddata->drm_fd = -1;
viddata->vulkan_mode = SDL_FALSE;
device->driverdata = viddata; device->driverdata = viddata;
/* Setup all functions that can be handled from this backend. */ /* Setup all functions that can be handled from this backend. */
@ -1328,8 +1330,6 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
KMSDRM_PlaneInfo plane_info = {0}; KMSDRM_PlaneInfo plane_info = {0};
EGLContext egl_context;
/********************************************************************/ /********************************************************************/
/* BLOCK 1: protect the PRIMARY PLANE before destroying the buffers */ /* BLOCK 1: protect the PRIMARY PLANE before destroying the buffers */
/* it's using, by making it point to the original CRTC buffer, */ /* it's using, by making it point to the original CRTC buffer, */
@ -1370,17 +1370,9 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
/***************************************************************************/ /***************************************************************************/
/* Destroy the EGL surface. */ /* Destroy the EGL surface. */
/* In this eglMakeCurrent() call, we disable the current EGL surface */
/* because we're going to destroy it, but DON'T disable the EGL context, */
/* because it won't be enabled again until the programs ask for a pageflip */
/* so we get to SwapWindow(). */
/* If we disable the context until then and a program tries to retrieve */
/* the context version info before calling for a pageflip, the program */
/* will get wrong info and we will be in trouble. */
/***************************************************************************/ /***************************************************************************/
egl_context = (EGLContext)SDL_GL_GetCurrentContext(); SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, egl_context);
if (windata->egl_surface != EGL_NO_SURFACE) { if (windata->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, windata->egl_surface); SDL_EGL_DestroySurface(_this, windata->egl_surface);
@ -1391,7 +1383,6 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
KMSDRM_gbm_surface_destroy(windata->gs); KMSDRM_gbm_surface_destroy(windata->gs);
windata->gs = NULL; windata->gs = NULL;
} }
} }
int int
@ -1470,17 +1461,27 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
return; return;
} }
if (!is_vulkan) { if ( !is_vulkan && dispdata->gbm_init ) {
/* Free cursor plane. */
KMSDRM_DeinitMouse(_this);
/* Destroy GBM surface and buffers. */
KMSDRM_DestroySurfaces(_this, window); KMSDRM_DestroySurfaces(_this, window);
/* Unload EGL library. */
if (_this->egl_data) { if (_this->egl_data) {
SDL_EGL_UnloadLibrary(_this); SDL_EGL_UnloadLibrary(_this);
} }
/* Free display plane, and destroy GBM device. */
if (dispdata->gbm_init) {
KMSDRM_DeinitMouse(_this);
KMSDRM_GBMDeinit(_this, dispdata); KMSDRM_GBMDeinit(_this, dispdata);
} }
else {
/* If we were in Vulkan mode, get out of it. */
if (viddata->vulkan_mode) {
viddata->vulkan_mode = SDL_FALSE;
}
} }
/********************************************/ /********************************************/
@ -1528,7 +1529,6 @@ KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) {
windata->output_x = 0; windata->output_x = 0;
} else { } else {
/* Normal non-fullscreen windows are scaled using the CRTC, /* Normal non-fullscreen windows are scaled using the CRTC,
so get output (CRTC) size and position, for AR correction. */ so get output (CRTC) size and position, for AR correction. */
ratio = (float)window->w / (float)window->h; ratio = (float)window->w / (float)window->h;
@ -1537,7 +1537,6 @@ KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) {
windata->output_w = dispdata->mode.vdisplay * ratio; windata->output_w = dispdata->mode.vdisplay * ratio;
windata->output_h = dispdata->mode.vdisplay; windata->output_h = dispdata->mode.vdisplay;
windata->output_x = (dispdata->mode.hdisplay - windata->output_w) / 2; windata->output_x = (dispdata->mode.hdisplay - windata->output_w) / 2;
} }
if (!is_vulkan) { if (!is_vulkan) {
@ -1704,6 +1703,11 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
drmModeConnector *conn = dispdata->connector->connector; drmModeConnector *conn = dispdata->connector->connector;
int i; int i;
/* Don't do anything if we are in Vulkan mode. */
if (viddata->vulkan_mode) {
return 0;
}
if (!modedata) { if (!modedata) {
return SDL_SetError("Mode doesn't have an associated index"); return SDL_SetError("Mode doesn't have an associated index");
} }
@ -1736,11 +1740,12 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *dispdata = display->driverdata; SDL_DisplayData *dispdata = display->driverdata;
SDL_bool is_vulkan = window->flags & SDL_WINDOW_VULKAN; /* Is this a VK window? */ SDL_bool is_vulkan = window->flags & SDL_WINDOW_VULKAN; /* Is this a VK window? */
SDL_bool vulkan_mode = viddata->vulkan_mode; /* Do we have any Vulkan windows? */
NativeDisplayType egl_display; NativeDisplayType egl_display;
float ratio; float ratio;
int ret = 0; int ret = 0;
if ( !(dispdata->gbm_init) && (!is_vulkan)) { if ( !(dispdata->gbm_init) && !is_vulkan && !vulkan_mode ) {
/* Reopen FD, create gbm dev, setup display plane, etc,. /* Reopen FD, create gbm dev, setup display plane, etc,.
but only when we come here for the first time, but only when we come here for the first time,
and only if it's not a VK window. */ and only if it's not a VK window. */
@ -1804,7 +1809,8 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
windata->viddata = viddata; windata->viddata = viddata;
window->driverdata = windata; window->driverdata = windata;
if (!is_vulkan) { if (!is_vulkan && !vulkan_mode) {
/* Create the window surfaces. Needs the window diverdata in place. */
if ((ret = KMSDRM_CreateSurfaces(_this, window))) { if ((ret = KMSDRM_CreateSurfaces(_this, window))) {
goto cleanup; goto cleanup;
} }
@ -1827,6 +1833,9 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
viddata->windows[viddata->num_windows++] = window; viddata->windows[viddata->num_windows++] = window;
/* If we have just created a Vulkan window, establish that we are in Vulkan mode now. */
viddata->vulkan_mode = is_vulkan;
/* Focus on the newly created window */ /* Focus on the newly created window */
SDL_SetMouseFocus(window); SDL_SetMouseFocus(window);
SDL_SetKeyboardFocus(window); SDL_SetKeyboardFocus(window);

View File

@ -57,6 +57,8 @@ typedef struct SDL_VideoData
SDL_bool video_init; /* Has VideoInit succeeded? */ SDL_bool video_init; /* Has VideoInit succeeded? */
SDL_bool vulkan_mode; /* Are we in Vulkan mode? One VK window is enough. */
} SDL_VideoData; } SDL_VideoData;
typedef struct plane { typedef struct plane {