SDL: kmsdrm: fix SetDisplayMode binding the the wrong surface / context

From 4c965b7a8d4228640377e27d57d66ff95decb6da Mon Sep 17 00:00:00 2001
From: Anthony Pesch <[EMAIL REDACTED]>
Date: Sun, 23 May 2021 16:09:27 -0400
Subject: [PATCH] kmsdrm: fix SetDisplayMode binding the the wrong surface /
 context

SetDisplayMode needs to recreate the EGL surfaces, which then need to be
bound along with the correct context in each rendering thread

commit 3a1d7d9c9ac670bf35cfa8ebf3706a1e2a3e5de4 removed this behavior which
has broken using SetDisplayMode when rendering with multiple contexts

the commit message was rather vague, but if the surfaces do need to be
created immediately, this process probably needs to be split such that
surface is created immediately, but the binding is deferred
---
 src/video/kmsdrm/SDL_kmsdrmopengles.c | 5 +++++
 src/video/kmsdrm/SDL_kmsdrmvideo.c    | 9 ++++++---
 src/video/kmsdrm/SDL_kmsdrmvideo.h    | 2 +-
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index ee7e3923d7..7b28c55bc6 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -97,6 +97,11 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
        even if you do async flips. */
     uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT;
 
+    /* Recreate the GBM / EGL surfaces if the display mode has changed */
+    if (windata->egl_surface_dirty) {
+        KMSDRM_CreateSurfaces(_this, window);
+    }
+
     /* Wait for confirmation that the next front buffer has been flipped, at which
        point the previous front buffer can be released */
     if (!KMSDRM_WaitPageflip(_this, windata)) {
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index 9704d0e4f6..3f9de064ee 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -953,6 +953,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
     egl_context = (EGLContext)SDL_GL_GetCurrentContext();
     ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
 
+    windata->egl_surface_dirty = SDL_FALSE;
+
 cleanup:
 
     if (ret) {
@@ -1075,10 +1077,11 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
 
     for (i = 0; i < viddata->num_windows; i++) {
         SDL_Window *window = viddata->windows[i];
+        SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
 
-        if (KMSDRM_CreateSurfaces(_this, window)) {
-            return -1;
-        }
+        /* Can't recreate EGL surfaces right now, need to wait until SwapWindow
+           so the correct thread-local surface and context state are available */
+        windata->egl_surface_dirty = SDL_TRUE;
 
         /* Tell app about the window resize */
         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode->w, mode->h);
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index 89b2381866..18e90abc22 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -99,7 +99,7 @@ typedef struct SDL_WindowData
     SDL_bool double_buffer;
 
     EGLSurface egl_surface;
-
+    SDL_bool egl_surface_dirty;
 } SDL_WindowData;
 
 typedef struct KMSDRM_FBInfo