SDL: Fixed order of operations problem when tearing down the window

From d305bc6d5565a675ccdc58ac432bd6978ccc3030 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 17 Dec 2022 07:09:24 -0800
Subject: [PATCH] Fixed order of operations problem when tearing down the
 window

Make sure the window framebuffer is cleaned up before shutting down OpenGL, as it might be implemented using an OpenGL texture.

Fixes this call stack:

(gdb) p _this
$1 = (SDL_VideoDevice *) 0x42e360
(gdb) p _this->egl_data
$2 = (struct SDL_EGL_VideoData *) 0x0

---
 src/video/SDL_video.c | 39 +++++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 26dde67da526..9aaf6ba98f7c 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1876,6 +1876,13 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
         window->surface_valid = SDL_FALSE;
     }
 
+    if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
+        if (_this->DestroyWindowFramebuffer) {
+            _this->DestroyWindowFramebuffer(_this, window);
+        }
+        _this->checked_texture_framebuffer = SDL_FALSE;
+    }
+
     if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) {
         if (flags & SDL_WINDOW_OPENGL) {
             need_gl_load = SDL_TRUE;
@@ -1906,12 +1913,6 @@ int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
         SDL_Vulkan_UnloadLibrary();
     }
 
-    if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
-        if (_this->DestroyWindowFramebuffer) {
-            _this->DestroyWindowFramebuffer(_this, window);
-        }
-    }
-
     if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
         _this->DestroyWindow(_this, window);
     }
@@ -3084,30 +3085,32 @@ void SDL_DestroyWindow(SDL_Window *window)
         SDL_SetMouseFocus(NULL);
     }
 
-    /* make no context current if this is the current context window. */
-    if (window->flags & SDL_WINDOW_OPENGL) {
-        if (_this->current_glwin == window) {
-            SDL_GL_MakeCurrent(window, NULL);
-        }
-    }
-
     if (window->surface) {
         window->surface->flags &= ~SDL_DONTFREE;
         SDL_FreeSurface(window->surface);
         window->surface = NULL;
         window->surface_valid = SDL_FALSE;
     }
+
+    if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
+        if (_this->DestroyWindowFramebuffer) {
+            _this->DestroyWindowFramebuffer(_this, window);
+        }
+    }
+
+    /* make no context current if this is the current context window. */
+    if (window->flags & SDL_WINDOW_OPENGL) {
+        if (_this->current_glwin == window) {
+            SDL_GL_MakeCurrent(window, NULL);
+        }
+    }
     if (window->flags & SDL_WINDOW_OPENGL) {
         SDL_GL_UnloadLibrary();
     }
     if (window->flags & SDL_WINDOW_VULKAN) {
         SDL_Vulkan_UnloadLibrary();
     }
-    if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
-        if (_this->DestroyWindowFramebuffer) {
-            _this->DestroyWindowFramebuffer(_this, window);
-        }
-    }
+
     if (_this->DestroyWindow) {
         _this->DestroyWindow(_this, window);
     }