[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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index 663bc21..b8ec424 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -822,6 +822,8 @@ KMSDRM_CreateDevice(int devindex)
viddata->devindex = devindex;
viddata->drm_fd = -1;
+ viddata->vulkan_mode = SDL_FALSE;
+
device->driverdata = viddata;
/* 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);
KMSDRM_PlaneInfo plane_info = {0};
- EGLContext egl_context;
-
/********************************************************************/
/* BLOCK 1: protect the PRIMARY PLANE before destroying the buffers */
/* 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. */
- /* 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_context);
+ SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (windata->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, windata->egl_surface);
@@ -1391,7 +1383,6 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
KMSDRM_gbm_surface_destroy(windata->gs);
windata->gs = NULL;
}
-
}
int
@@ -1470,16 +1461,26 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
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);
+ /* Unload EGL library. */
if (_this->egl_data) {
SDL_EGL_UnloadLibrary(_this);
}
+ /* Free display plane, and destroy GBM device. */
+ KMSDRM_GBMDeinit(_this, dispdata);
+ }
- if (dispdata->gbm_init) {
- KMSDRM_DeinitMouse(_this);
- 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;
} else {
-
/* Normal non-fullscreen windows are scaled using the CRTC,
so get output (CRTC) size and position, for AR correction. */
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_h = dispdata->mode.vdisplay;
windata->output_x = (dispdata->mode.hdisplay - windata->output_w) / 2;
-
}
if (!is_vulkan) {
@@ -1704,6 +1703,11 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
drmModeConnector *conn = dispdata->connector->connector;
int i;
+ /* Don't do anything if we are in Vulkan mode. */
+ if (viddata->vulkan_mode) {
+ return 0;
+ }
+
if (!modedata) {
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_DisplayData *dispdata = display->driverdata;
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;
float ratio;
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,.
but only when we come here for the first time,
and only if it's not a VK window. */
@@ -1804,7 +1809,8 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
windata->viddata = viddata;
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))) {
goto cleanup;
}
@@ -1827,6 +1833,9 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * 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 */
SDL_SetMouseFocus(window);
SDL_SetKeyboardFocus(window);
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index e58c922..edb0e16 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -57,6 +57,8 @@ typedef struct SDL_VideoData
SDL_bool video_init; /* Has VideoInit succeeded? */
+ SDL_bool vulkan_mode; /* Are we in Vulkan mode? One VK window is enough. */
+
} SDL_VideoData;
typedef struct plane {