diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index b12aea7dac..305203a4a2 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -516,44 +516,28 @@ public: sint32 x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(defaultDisplay); sint32 y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(defaultDisplay); - // Get saved window size - sint32 width = gConfigGeneral.window_width; - sint32 height = gConfigGeneral.window_height; - if (width <= 0) width = 640; - if (height <= 0) height = 480; - - // Create window in window first rather than fullscreen so we have the display the window is on first - uint32 flags = SDL_WINDOW_RESIZABLE; - if (gConfigGeneral.drawing_engine == DRAWING_ENGINE_OPENGL) - { - flags |= SDL_WINDOW_OPENGL; - } - - _window = SDL_CreateWindow(OPENRCT2_NAME, x, y, width, height, flags); - if (_window == nullptr) - { - SDLException::Throw("SDL_CreateWindow(...)"); - } - - SDL_SetWindowMinimumSize(_window, 720, 480); - SetCursorTrap(gConfigGeneral.trap_cursor); - _platformUiContext->SetWindowIcon(_window); - - // Initialise the surface, palette and draw buffer - OnResize(width, height); - - UpdateFullscreenResolutions(); - SetFullscreenMode((FULLSCREEN_MODE)gConfigGeneral.fullscreen_mode); + CreateWindow(x, y); // Check if steam overlay renderer is loaded into the process _steamOverlayActive = _platformUiContext->IsSteamOverlayAttached(); - TriggerResize(); } void CloseWindow() override { drawing_engine_dispose(); SDL_DestroyWindow(_window); + _window = nullptr; + } + + void RecreateWindow() override + { + // Use the position of the current window for the new window + sint32 x, y; + SDL_SetWindowFullscreen(_window, 0); + SDL_GetWindowPosition(_window, &x, &y); + + CloseWindow(); + CreateWindow(x, y); } void ShowMessageBox(const std::string &message) override @@ -646,6 +630,41 @@ public: private: + void CreateWindow(sint32 x, sint32 y) + { + // Get saved window size + sint32 width = gConfigGeneral.window_width; + sint32 height = gConfigGeneral.window_height; + if (width <= 0) width = 640; + if (height <= 0) height = 480; + + // Create window in window first rather than fullscreen so we have the display the window is on first + uint32 flags = SDL_WINDOW_RESIZABLE; + if (gConfigGeneral.drawing_engine == DRAWING_ENGINE_OPENGL) + { + flags |= SDL_WINDOW_OPENGL; + } + + _window = SDL_CreateWindow(OPENRCT2_NAME, x, y, width, height, flags); + if (_window == nullptr) + { + SDLException::Throw("SDL_CreateWindow(...)"); + } + + SDL_SetWindowMinimumSize(_window, 720, 480); + SetCursorTrap(gConfigGeneral.trap_cursor); + _platformUiContext->SetWindowIcon(_window); + + // Initialise the surface, palette and draw buffer + drawing_engine_init(); + OnResize(width, height); + + UpdateFullscreenResolutions(); + SetFullscreenMode((FULLSCREEN_MODE)gConfigGeneral.fullscreen_mode); + + TriggerResize(); + } + void OnResize(sint32 width, sint32 height) { // Scale the native window size to the game's canvas size diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.cpp index 587d51ea5a..46bdd6b6fa 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.cpp @@ -121,8 +121,14 @@ static const char * TryLoadAllProcAddresses() namespace OpenGLState { - uint16 ActiveTexture = UINT16_MAX; - GLuint CurrentProgram = UINT32_MAX; + uint16 ActiveTexture; + GLuint CurrentProgram; + + void Reset() + { + ActiveTexture = UINT16_MAX; + CurrentProgram = UINT32_MAX; + } } void OpenGLAPI::SetTexture(uint16 index, GLenum type, GLuint texture) @@ -136,6 +142,8 @@ void OpenGLAPI::SetTexture(uint16 index, GLenum type, GLuint texture) bool OpenGLAPI::Initialise() { + OpenGLState::Reset(); + #ifdef OPENGL_NO_LINK const char * failedProcName = TryLoadAllProcAddresses(); if (failedProcName != nullptr) diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.h b/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.h index bb505a46e6..71360784c6 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.h +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLAPI.h @@ -198,4 +198,6 @@ namespace OpenGLState { extern uint16 ActiveTexture; extern GLuint CurrentProgram; + + void Reset(); } diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 7d88a16a2e..c3c9687f6e 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -663,6 +663,11 @@ extern "C" return GetContext()->GetUiContext()->SetFullscreenMode((FULLSCREEN_MODE)mode); } + void context_recreate_window() + { + GetContext()->GetUiContext()->RecreateWindow(); + } + sint32 context_get_resolutions(Resolution * * outResolutions) { auto resolutions = GetContext()->GetUiContext()->GetFullscreenResolutions(); diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index fb3892d46b..76ec8c6be6 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -127,6 +127,7 @@ extern "C" bool context_is_input_active(); void context_trigger_resize(); void context_set_fullscreen_mode(sint32 mode); + void context_recreate_window(); sint32 context_get_resolutions(struct Resolution * * outResolutions); sint32 context_get_width(); sint32 context_get_height(); diff --git a/src/openrct2/drawing/NewDrawing.cpp b/src/openrct2/drawing/NewDrawing.cpp index 83d0bdfdca..dcc57a894e 100644 --- a/src/openrct2/drawing/NewDrawing.cpp +++ b/src/openrct2/drawing/NewDrawing.cpp @@ -57,20 +57,18 @@ extern "C" return _drawingEngineType; } - bool drawing_engine_requires_restart(sint32 srcEngine, sint32 dstEngine) + bool drawing_engine_requires_new_window(sint32 srcEngine, sint32 dstEngine) { - // Linux requires a restart. This could be improved in the future by recreating the window, - // https://github.com/OpenRCT2/OpenRCT2/issues/2015 - bool requiresRestart = true; #ifdef _WIN32 - if (dstEngine != DRAWING_ENGINE_OPENGL) + if (srcEngine != DRAWING_ENGINE_OPENGL && dstEngine != DRAWING_ENGINE_OPENGL) { // Windows is apparently able to switch to hardware rendering on the fly although // using the same window in an unaccelerated and accelerated context is unsupported by SDL2 - requiresRestart = false; + return false; } #endif - return requiresRestart; + + return true; } void drawing_engine_init() @@ -135,13 +133,11 @@ extern "C" void drawing_engine_resize() { - if (_drawingEngine == nullptr) + if (_drawingEngine != nullptr) { - drawing_engine_init(); + IUiContext * uiContext = GetContext()->GetUiContext(); + _drawingEngine->Resize(uiContext->GetWidth(), uiContext->GetHeight()); } - - IUiContext * uiContext = GetContext()->GetUiContext(); - _drawingEngine->Resize(uiContext->GetWidth(), uiContext->GetHeight()); } void drawing_engine_set_palette(const rct_palette_entry * colours) diff --git a/src/openrct2/drawing/NewDrawing.h b/src/openrct2/drawing/NewDrawing.h index 30ef3ea140..54c4042605 100644 --- a/src/openrct2/drawing/NewDrawing.h +++ b/src/openrct2/drawing/NewDrawing.h @@ -27,7 +27,7 @@ extern "C" extern rct_string_id DrawingEngineStringIds[3]; sint32 drawing_engine_get_type(); -bool drawing_engine_requires_restart(sint32 srcEngine, sint32 dstEngine); +bool drawing_engine_requires_new_window(sint32 srcEngine, sint32 dstEngine); void drawing_engine_init(); void drawing_engine_resize(); void drawing_engine_set_palette(const rct_palette_entry * colours); diff --git a/src/openrct2/platform/platform.h b/src/openrct2/platform/platform.h index e0c82ff805..6eb40a6a0e 100644 --- a/src/openrct2/platform/platform.h +++ b/src/openrct2/platform/platform.h @@ -86,7 +86,7 @@ void platform_draw_require_end(); void platform_free(); void platform_update_palette(const uint8 *colours, sint32 start_index, sint32 num_colours); void platform_toggle_windowed_mode(); -void platform_refresh_video(); +void platform_refresh_video(bool recreate_window); void platform_get_date_utc(rct2_date *out_date); void platform_get_time_utc(rct2_time *out_time); void platform_get_date_local(rct2_date *out_date); diff --git a/src/openrct2/platform/shared.c b/src/openrct2/platform/shared.c index f9aa539bd6..bbfa235a71 100644 --- a/src/openrct2/platform/shared.c +++ b/src/openrct2/platform/shared.c @@ -152,11 +152,19 @@ void platform_toggle_windowed_mode() config_save_default(); } -void platform_refresh_video() +void platform_refresh_video(bool recreate_window) { - drawing_engine_dispose(); - drawing_engine_init(); - drawing_engine_resize(); + if (recreate_window) + { + context_recreate_window(); + } + else + { + drawing_engine_dispose(); + drawing_engine_init(); + drawing_engine_resize(); + } + drawing_engine_set_palette(gPalette); gfx_invalidate_screen(); } diff --git a/src/openrct2/ui/DummyUiContext.cpp b/src/openrct2/ui/DummyUiContext.cpp index 3b3dab1d67..8aa168560e 100644 --- a/src/openrct2/ui/DummyUiContext.cpp +++ b/src/openrct2/ui/DummyUiContext.cpp @@ -33,6 +33,7 @@ namespace OpenRCT2 { namespace Ui public: void CreateWindow() override { } void CloseWindow() override { } + void RecreateWindow() override { } void * GetWindow() override { return nullptr; } sint32 GetWidth() override { return 0; } sint32 GetHeight() override { return 0; } diff --git a/src/openrct2/ui/UiContext.h b/src/openrct2/ui/UiContext.h index 49fe1ec225..88bf49fabd 100644 --- a/src/openrct2/ui/UiContext.h +++ b/src/openrct2/ui/UiContext.h @@ -94,6 +94,7 @@ namespace OpenRCT2 // Window virtual void CreateWindow() abstract; virtual void CloseWindow() abstract; + virtual void RecreateWindow() abstract; virtual void * GetWindow() abstract; virtual sint32 GetWidth() abstract; virtual sint32 GetHeight() abstract; diff --git a/src/openrct2/windows/options.c b/src/openrct2/windows/options.c index 63e235446c..e7a7b03216 100644 --- a/src/openrct2/windows/options.c +++ b/src/openrct2/windows/options.c @@ -639,7 +639,7 @@ static void window_options_mouseup(rct_window *w, rct_widgetindex widgetIndex) break; case WIDX_MINIMIZE_FOCUS_LOSS: gConfigGeneral.minimize_fullscreen_focus_loss ^= 1; - platform_refresh_video(); + platform_refresh_video(false); config_save_default(); window_invalidate(w); break; @@ -1308,11 +1308,8 @@ static void window_options_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dstEngine = dropdownIndex; gConfigGeneral.drawing_engine = (uint8)dstEngine; - if (drawing_engine_requires_restart(srcEngine, dstEngine)) { - window_error_open(STR_RESTART_REQUIRED, STR_NONE); - } else { - platform_refresh_video(); - } + bool recreate_window = drawing_engine_requires_new_window(srcEngine, dstEngine); + platform_refresh_video(recreate_window); config_save_default(); window_invalidate(w); }