From 14ece2ac9058dcb21d359a58b652f5658ae675d0 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Wed, 31 Aug 2022 12:21:08 +0200 Subject: [PATCH] Ports: Support "restarts" in SDL2 SDL2 applications are prone to reinitializing the SDL components when, for example, changing the display resolution. This would lead to crashes since we were doing things in the wrong order. * We now decouple `GLContext` from `SDL_Window` a bit more, allowing the window to be destroyed before the GLContext. * Do not quit the `GUI::Application`, let our event loop handle exiting These changes allow changing the display resolution in the Quake3 port. --- ...0001-Add-SerenityOS-platform-support.patch | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/Ports/SDL2/patches/0001-Add-SerenityOS-platform-support.patch b/Ports/SDL2/patches/0001-Add-SerenityOS-platform-support.patch index c1a60b84ba8..f6fcd03454e 100644 --- a/Ports/SDL2/patches/0001-Add-SerenityOS-platform-support.patch +++ b/Ports/SDL2/patches/0001-Add-SerenityOS-platform-support.patch @@ -34,8 +34,8 @@ Co-Authored-By: circl src/video/serenity/SDL_serenitymessagebox.h | 38 ++ src/video/serenity/SDL_serenitymouse.cpp | 142 +++++ src/video/serenity/SDL_serenitymouse.h | 39 ++ - src/video/serenity/SDL_serenityvideo.cpp | 600 ++++++++++++++++++ - src/video/serenity/SDL_serenityvideo.h | 98 +++ + src/video/serenity/SDL_serenityvideo.cpp | 597 ++++++++++++++++++ + src/video/serenity/SDL_serenityvideo.h | 101 +++ 20 files changed, 1292 insertions(+), 25 deletions(-) create mode 100644 src/audio/serenity/SDL_serenityaudio.cpp create mode 100644 src/audio/serenity/SDL_serenityaudio.h @@ -862,10 +862,10 @@ index 0000000..039f036 +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/serenity/SDL_serenityvideo.cpp b/src/video/serenity/SDL_serenityvideo.cpp new file mode 100644 -index 0000000..85e69ef +index 0000000..e222405 --- /dev/null +++ b/src/video/serenity/SDL_serenityvideo.cpp -@@ -0,0 +1,600 @@ +@@ -0,0 +1,597 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga @@ -904,14 +904,14 @@ index 0000000..85e69ef +# include "SDL_serenitymouse.h" +# include "SDL_serenityvideo.h" + -+# include +# include -+# include +# include +# include +# include +# include +# include ++# include ++# include + +static SDL_Scancode scancode_map[] = { + SDL_SCANCODE_UNKNOWN, @@ -1112,11 +1112,12 @@ index 0000000..85e69ef + +int SERENITY_VideoInit(_THIS) +{ -+ VERIFY(!g_app); -+ g_app = GUI::Application::construct(0, nullptr); -+ g_app->set_quit_when_last_window_deleted(false); ++ dbgln("{}: Initialising SDL application", __FUNCTION__); + -+ dbgln("SDL2: Initialising SDL application"); ++ if (!g_app) { ++ g_app = GUI::Application::construct(0, nullptr); ++ g_app->set_quit_when_last_window_deleted(false); ++ } + + SERENITY_InitMouse(_this); + @@ -1131,9 +1132,8 @@ index 0000000..85e69ef + mode.refresh_rate = 60; + mode.driverdata = nullptr; + -+ if (SDL_AddBasicVideoDisplay(&mode) < 0) { ++ if (SDL_AddBasicVideoDisplay(&mode) < 0) + return -1; -+ } + + SDL_AddDisplayMode(&_this->displays[0], &mode); + @@ -1152,13 +1152,11 @@ index 0000000..85e69ef +{ + dbgln("SERENITY_VideoQuit"); + SERENITY_QuitMouse(_this); -+ g_app->quit(); +} + -+SerenitySDLWidget::SerenitySDLWidget(SDL_Window* window) -+ : m_sdl_window(window) ++SerenitySDLWidget::SerenitySDLWidget(SDL_Window* sdl_window) ++ : m_sdl_window(sdl_window) +{ -+ update(); +} + +void SerenitySDLWidget::paint_event(GUI::PaintEvent& event) @@ -1248,7 +1246,8 @@ index 0000000..85e69ef + +int Serenity_CreateWindow(_THIS, SDL_Window* window) +{ -+ dbgln("SDL2: Creating new window of size {}x{}", window->w, window->h); ++ dbgln("{}: Creating new window of size {}x{}", __FUNCTION__, window->w, window->h); ++ + auto w = new SerenityPlatformWindow(window); + window->driverdata = w; + w->window()->set_double_buffering_enabled(false); @@ -1357,7 +1356,7 @@ index 0000000..85e69ef +int Serenity_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format, + void** pixels, int* pitch) +{ -+ dbgln("SDL2: Creating a new framebuffer of size {}x{}", window->w, window->h); ++ dbgln("{}: Creating a new framebuffer of size {}x{}", __FUNCTION__, window->w, window->h); + auto win = SerenityPlatformWindow::from_sdl_window(window); + *format = SDL_PIXELFORMAT_RGB888; + auto bitmap_or_error = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRx8888, {window->w, window->h}); @@ -1366,7 +1365,6 @@ index 0000000..85e69ef + win->widget()->m_buffer = bitmap_or_error.release_value(); + *pitch = win->widget()->m_buffer->pitch(); + *pixels = win->widget()->m_buffer->scanline(0); -+ dbgln("Created framebuffer {}x{}", win->widget()->width(), win->widget()->height()); + return 0; +} + @@ -1385,32 +1383,29 @@ index 0000000..85e69ef +void Serenity_DestroyWindowFramebuffer(_THIS, SDL_Window* window) +{ + auto widget = SerenityPlatformWindow::from_sdl_window(window)->widget(); -+ dbgln("SDL2: Destroy framebuffer {}", widget->m_buffer->size()); ++ dbgln("{}: Destroy framebuffer {}", __FUNCTION__, widget->m_buffer->size()); + widget->m_buffer = nullptr; +} + +SDL_GLContext Serenity_GL_CreateContext(_THIS, SDL_Window* window) +{ -+ auto win = SerenityPlatformWindow::from_sdl_window(window); ++ auto platform_window = SerenityPlatformWindow::from_sdl_window(window); + + Uint32 format; + void* pixels; + int pitch; + Serenity_CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch); + -+ win->widget()->m_gl_context = GL::create_context(*win->widget()->m_buffer); -+ GL::make_context_current(win->widget()->m_gl_context); -+ -+ return new SerenityGLContext(*window); ++ auto gl_context = GL::create_context(*platform_window->widget()->m_buffer); ++ auto serenity_gl_context = new SerenityGLContext(move(gl_context)); ++ platform_window->set_serenity_gl_context(serenity_gl_context); ++ GL::make_context_current(&serenity_gl_context->gl_context()); ++ return serenity_gl_context; +} + +void Serenity_GL_DeleteContext(_THIS, SDL_GLContext context) +{ + auto platform_context = static_cast(context); -+ auto sdl_window = platform_context->sdl_window(); -+ auto platform_window = SerenityPlatformWindow::from_sdl_window(&sdl_window); -+ -+ platform_window->widget()->m_gl_context = nullptr; + delete platform_context; +} + @@ -1449,17 +1444,19 @@ index 0000000..85e69ef + return 0; + + auto platform_window = SerenityPlatformWindow::from_sdl_window(window); -+ GL::make_context_current(platform_window->widget()->m_gl_context); ++ auto serenity_gl_context = static_cast(context); ++ platform_window->set_serenity_gl_context(serenity_gl_context); ++ GL::make_context_current(&serenity_gl_context->gl_context()); + return 0; +} + +int Serenity_GL_SwapWindow(_THIS, SDL_Window* window) +{ -+ auto win = SerenityPlatformWindow::from_sdl_window(window); -+ if (win->widget()->m_gl_context) -+ GL::present_context(win->widget()->m_gl_context); ++ auto platform_window = SerenityPlatformWindow::from_sdl_window(window); ++ if (platform_window->serenity_gl_context()) ++ GL::present_context(&platform_window->serenity_gl_context()->gl_context()); + -+ win->widget()->repaint(); ++ platform_window->widget()->repaint(); + return 0; +} + @@ -1468,10 +1465,10 @@ index 0000000..85e69ef +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/serenity/SDL_serenityvideo.h b/src/video/serenity/SDL_serenityvideo.h new file mode 100644 -index 0000000..b5c6759 +index 0000000..f74e1bd --- /dev/null +++ b/src/video/serenity/SDL_serenityvideo.h -@@ -0,0 +1,98 @@ +@@ -0,0 +1,101 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga @@ -1508,7 +1505,6 @@ index 0000000..b5c6759 +public: + explicit SerenitySDLWidget(SDL_Window*); + RefPtr m_buffer; -+ OwnPtr m_gl_context; + +protected: + void paint_event(GUI::PaintEvent&) override; @@ -1531,11 +1527,24 @@ index 0000000..b5c6759 + SDL_Window* m_sdl_window = nullptr; +}; + ++class SerenityGLContext final { ++public: ++ explicit SerenityGLContext(NonnullOwnPtr gl_context) ++ : m_gl_context(move(gl_context)) ++ { ++ } ++ ++ GL::GLContext& gl_context() { return *m_gl_context; } ++ ++private: ++ NonnullOwnPtr m_gl_context; ++}; ++ +class SerenityPlatformWindow final { +public: -+ SerenityPlatformWindow(SDL_Window* sdl_window) -+ : m_window(GUI::Window::construct()) -+ , m_widget(SerenitySDLWidget::construct(sdl_window)) ++ explicit SerenityPlatformWindow(SDL_Window* sdl_window) ++ : m_window(MUST(GUI::Window::try_create())) ++ , m_widget(MUST(SerenitySDLWidget::try_create(sdl_window))) + { + m_window->resize(sdl_window->w, sdl_window->h); + m_window->set_resizable(false); @@ -1546,27 +1555,18 @@ index 0000000..b5c6759 + return static_cast(window->driverdata); + } + ++ SerenityGLContext* serenity_gl_context() { return m_serenity_gl_context; } ++ void set_serenity_gl_context(SerenityGLContext* serenity_gl_context) { m_serenity_gl_context = serenity_gl_context; } ++ + NonnullRefPtr window() { return m_window; } + NonnullRefPtr widget() { return m_widget; } + +private: ++ SerenityGLContext* m_serenity_gl_context; + NonnullRefPtr m_window; + NonnullRefPtr m_widget; +}; + -+class SerenityGLContext final { -+public: -+ explicit SerenityGLContext(SDL_Window& sdl_window) -+ : m_sdl_window(sdl_window) -+ { -+ } -+ -+ SDL_Window& sdl_window() const { return m_sdl_window; } -+ -+private: -+ SDL_Window& m_sdl_window; -+}; -+ +#endif /* SDL_serenityvideo_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */