From 730ceb5c334ad63c229863513997dcaba2d20d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Wed, 30 Apr 2025 18:04:06 +0300 Subject: [PATCH] Adjust code, deprecate and fallback to HW if software was selected --- .../drawing/engines/DrawingEngineFactory.hpp | 6 +- src/openrct2-ui/windows/Options.cpp | 62 +++++------ src/openrct2/Context.cpp | 101 ++++++++++-------- src/openrct2/config/Config.cpp | 9 +- src/openrct2/drawing/IDrawingEngine.h | 2 +- src/openrct2/drawing/NewDrawing.cpp | 6 -- src/openrct2/drawing/NewDrawing.h | 2 - 7 files changed, 100 insertions(+), 88 deletions(-) diff --git a/src/openrct2-ui/drawing/engines/DrawingEngineFactory.hpp b/src/openrct2-ui/drawing/engines/DrawingEngineFactory.hpp index a5fc205d79..12aa974acb 100644 --- a/src/openrct2-ui/drawing/engines/DrawingEngineFactory.hpp +++ b/src/openrct2-ui/drawing/engines/DrawingEngineFactory.hpp @@ -10,14 +10,13 @@ #pragma once #include +#include #include namespace OpenRCT2::Ui { struct IUiContext; - [[nodiscard]] std::unique_ptr CreateSoftwareDrawingEngine( - const std::shared_ptr& uiContext); [[nodiscard]] std::unique_ptr CreateHardwareDisplayDrawingEngine( const std::shared_ptr& uiContext); #ifndef DISABLE_OPENGL @@ -33,8 +32,6 @@ namespace OpenRCT2::Ui { switch (type) { - case DrawingEngine::Software: - return CreateSoftwareDrawingEngine(uiContext); case DrawingEngine::SoftwareWithHardwareDisplay: return CreateHardwareDisplayDrawingEngine(uiContext); #ifndef DISABLE_OPENGL @@ -42,6 +39,7 @@ namespace OpenRCT2::Ui return CreateOpenGLDrawingEngine(uiContext); #endif default: + Guard::Fail("Unknown renderer: %u", static_cast(type)); return nullptr; } } diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index 79a5d90be0..d03c39ece6 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -426,8 +426,27 @@ namespace OpenRCT2::Ui::Windows window_options_misc_widgets, window_options_advanced_widgets, }; + // clang-format on + static constexpr std::pair kDrawingEngineChoices[] = { + { STR_DRAWING_ENGINE_SOFTWARE_WITH_HARDWARE_DISPLAY, DrawingEngine::SoftwareWithHardwareDisplay }, +#ifndef DISABLE_OPENGL + { STR_DRAWING_ENGINE_OPENGL, DrawingEngine::OpenGL }, +#endif + }; + + static constexpr int32_t getDrawingEngineIndex(DrawingEngine engine) + { + for (int32_t i = 0; i < static_cast(std::size(kDrawingEngineChoices)); ++i) + { + if (kDrawingEngineChoices[i].second == engine) + return i; + } + Guard::Fail("Unsupported drawing engine: %u", EnumValue(engine)); + return -1; + } + #pragma endregion class OptionsWindow final : public Window @@ -792,18 +811,14 @@ namespace OpenRCT2::Ui::Windows break; case WIDX_DRAWING_ENGINE_DROPDOWN: { - int32_t numItems = 3; -#ifdef DISABLE_OPENGL - numItems = 2; -#endif - + const auto numItems = static_cast(std::size(kDrawingEngineChoices)); for (int32_t i = 0; i < numItems; i++) { gDropdownItems[i].Format = STR_DROPDOWN_MENU_LABEL; - gDropdownItems[i].Args = DrawingEngineStringIds[i]; + gDropdownItems[i].Args = kDrawingEngineChoices[i].first; } ShowDropdown(widget, numItems); - Dropdown::SetChecked(EnumValue(Config::Get().general.DrawingEngine), true); + Dropdown::SetChecked(getDrawingEngineIndex(Config::Get().general.DrawingEngine), true); break; } case WIDX_SCALE_UP: @@ -859,11 +874,10 @@ namespace OpenRCT2::Ui::Windows } break; case WIDX_DRAWING_ENGINE_DROPDOWN: - if (dropdownIndex != EnumValue(Config::Get().general.DrawingEngine)) + if (DrawingEngine selectedEngine = kDrawingEngineChoices[dropdownIndex].second; + selectedEngine != Config::Get().general.DrawingEngine) { - DrawingEngine dstEngine = static_cast(dropdownIndex); - - Config::Get().general.DrawingEngine = dstEngine; + Config::Get().general.DrawingEngine = selectedEngine; RefreshVideo(); Config::Save(); Invalidate(); @@ -895,25 +909,11 @@ namespace OpenRCT2::Ui::Windows } // Disable Steam Overlay checkbox when using software or OpenGL rendering. - if (Config::Get().general.DrawingEngine == DrawingEngine::Software - || Config::Get().general.DrawingEngine == DrawingEngine::OpenGL) - { - disabled_widgets |= (1uLL << WIDX_STEAM_OVERLAY_PAUSE); - } - else - { - disabled_widgets &= ~(1uLL << WIDX_STEAM_OVERLAY_PAUSE); - } + // TODO: Check if this even works properly. + disabled_widgets |= (1uLL << WIDX_STEAM_OVERLAY_PAUSE); - // Disable changing VSync for Software engine, as we can't control its use of VSync - if (Config::Get().general.DrawingEngine == DrawingEngine::Software) - { - disabled_widgets |= (1uLL << WIDX_USE_VSYNC_CHECKBOX); - } - else - { - disabled_widgets &= ~(1uLL << WIDX_USE_VSYNC_CHECKBOX); - } + // VSync. + disabled_widgets &= ~(1uLL << WIDX_USE_VSYNC_CHECKBOX); SetCheckboxValue(WIDX_UNCAP_FPS_CHECKBOX, Config::Get().general.UncapFPS); SetCheckboxValue(WIDX_USE_VSYNC_CHECKBOX, Config::Get().general.UseVSync); @@ -925,7 +925,9 @@ namespace OpenRCT2::Ui::Windows // Dropdown captions for straightforward strings. widgets[WIDX_FULLSCREEN].text = FullscreenModeNames[Config::Get().general.FullscreenMode]; - widgets[WIDX_DRAWING_ENGINE].text = DrawingEngineStringIds[EnumValue(Config::Get().general.DrawingEngine)]; + + const auto selectedDrawingEngine = getDrawingEngineIndex(Config::Get().general.DrawingEngine); + widgets[WIDX_DRAWING_ENGINE].text = kDrawingEngineChoices[selectedDrawingEngine].first; } void DisplayDraw(DrawPixelInfo& dpi) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 02c1a307e1..8881e25133 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -136,7 +136,7 @@ namespace OpenRCT2 std::unique_ptr _gameScene; IScene* _activeScene = nullptr; - DrawingEngine _drawingEngineType = DrawingEngine::Software; + DrawingEngine _drawingEngineType = DrawingEngine::SoftwareWithHardwareDisplay; std::unique_ptr _drawingEngine; std::unique_ptr _painter; @@ -612,59 +612,74 @@ namespace OpenRCT2 { assert(_drawingEngine == nullptr); - _drawingEngineType = Config::Get().general.DrawingEngine; - - auto drawingEngineFactory = _uiContext->GetDrawingEngineFactory(); - auto drawingEngine = drawingEngineFactory->Create(_drawingEngineType, _uiContext); - - if (drawingEngine == nullptr) - { - if (_drawingEngineType == DrawingEngine::Software) + const auto initializeEngine = [&](DrawingEngine engine) -> std::unique_ptr { + try { - _drawingEngineType = DrawingEngine::None; - LOG_FATAL("Unable to create a drawing engine."); - exit(-1); + auto drawingEngineFactory = _uiContext->GetDrawingEngineFactory(); + auto drawingEngine = drawingEngineFactory->Create(engine, _uiContext); + if (drawingEngine == nullptr) + { + LOG_FATAL("Unable to create a drawing engine."); + return nullptr; + } + + drawingEngine->Initialise(); + drawingEngine->SetVSync(Config::Get().general.UseVSync); + + return drawingEngine; + } + catch (std::exception& ex) + { + LOG_ERROR(ex.what()); + LOG_ERROR("Unable to initialise drawing engine."); + + return nullptr; + } + return nullptr; + }; + + auto drawingEngineType = Config::Get().general.DrawingEngine; + if (drawingEngineType == DrawingEngine::SoftwareDeprecated) + { + drawingEngineType = DrawingEngine::SoftwareWithHardwareDisplay; + } + + // Attempt to create drawing engine of the type specified in the config. + { + auto drawingEngine = initializeEngine(_drawingEngineType); + if (drawingEngine != nullptr) + { + _drawingEngine = std::move(drawingEngine); } else { - LOG_ERROR("Unable to create drawing engine. Falling back to software."); - - // Fallback to software - Config::Get().general.DrawingEngine = DrawingEngine::Software; - Config::Save(); - DrawingEngineInit(); - } - } - else - { - try - { - drawingEngine->Initialise(); - drawingEngine->SetVSync(Config::Get().general.UseVSync); - _drawingEngine = std::move(drawingEngine); - } - catch (const std::exception& ex) - { - if (_drawingEngineType == DrawingEngine::Software) + // If the drawing engine creation failed, try to create a software engine. + if (drawingEngineType == DrawingEngine::OpenGL) { - _drawingEngineType = DrawingEngine::None; - LOG_ERROR(ex.what()); - LOG_FATAL("Unable to initialise a drawing engine."); - exit(-1); - } - else - { - LOG_ERROR(ex.what()); - LOG_ERROR("Unable to initialise drawing engine. Falling back to software."); + drawingEngineType = DrawingEngine::SoftwareWithHardwareDisplay; - // Fallback to software - Config::Get().general.DrawingEngine = DrawingEngine::Software; + Config::Get().general.DrawingEngine = _drawingEngineType; Config::Save(); - DrawingEngineInit(); + + LOG_ERROR("Trying fallback back to software..."); + + drawingEngine = initializeEngine(_drawingEngineType); + if (drawingEngine != nullptr) + { + _drawingEngine = std::move(drawingEngine); + } + else + { + LOG_FATAL("Unable to create any renderer."); + exit(-1); + } } } } + Config::Get().general.DrawingEngine = drawingEngineType; + Config::Save(); + WindowCheckAllValidZoom(); } diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index a76719edf3..7a560bec0b 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -101,7 +101,6 @@ namespace OpenRCT2::Config }); static const auto Enum_DrawingEngine = ConfigEnum({ - ConfigEnumEntry("SOFTWARE", DrawingEngine::Software), ConfigEnumEntry("SOFTWARE_HWD", DrawingEngine::SoftwareWithHardwareDisplay), ConfigEnumEntry("OPENGL", DrawingEngine::OpenGL), }); @@ -212,7 +211,7 @@ namespace OpenRCT2::Config // Default config setting is false until the games canvas can be separated from the effect model->DayNightCycle = reader->GetBoolean("day_night_cycle", false); - const bool isHardware = model->DrawingEngine != DrawingEngine::Software; + const bool isHardware = true; model->EnableLightFx = isHardware && reader->GetBoolean("enable_light_fx", false); model->EnableLightFxForVehicles = isHardware && reader->GetBoolean("enable_light_fx_for_vehicles", false); model->UpperCaseBanners = reader->GetBoolean("upper_case_banners", false); @@ -265,6 +264,12 @@ namespace OpenRCT2::Config model->FileBrowserShowSizeColumn = reader->GetBoolean("file_browser_show_size_column", true); model->FileBrowserShowDateColumn = reader->GetBoolean("file_browser_show_date_column", true); model->FileBrowserShowPreviews = reader->GetBoolean("file_browser_show_previews", true); + + // Used to be an option but is now removed, SoftwareWithHardwareDisplay substitutes for Software. + if (model->DrawingEngine == DrawingEngine::SoftwareDeprecated) + { + model->DrawingEngine = DrawingEngine::SoftwareWithHardwareDisplay; + } } } diff --git a/src/openrct2/drawing/IDrawingEngine.h b/src/openrct2/drawing/IDrawingEngine.h index 7c132e07c8..658d52004f 100644 --- a/src/openrct2/drawing/IDrawingEngine.h +++ b/src/openrct2/drawing/IDrawingEngine.h @@ -19,7 +19,7 @@ enum class DrawingEngine : int32_t { None = -1, - Software, + SoftwareDeprecated, SoftwareWithHardwareDisplay, OpenGL, Count, diff --git a/src/openrct2/drawing/NewDrawing.cpp b/src/openrct2/drawing/NewDrawing.cpp index 96e4139116..a22bc8b9af 100644 --- a/src/openrct2/drawing/NewDrawing.cpp +++ b/src/openrct2/drawing/NewDrawing.cpp @@ -28,12 +28,6 @@ using namespace OpenRCT2::Drawing; using namespace OpenRCT2::Paint; using namespace OpenRCT2::Ui; -StringId DrawingEngineStringIds[] = { - STR_DRAWING_ENGINE_SOFTWARE, - STR_DRAWING_ENGINE_SOFTWARE_WITH_HARDWARE_DISPLAY, - STR_DRAWING_ENGINE_OPENGL, -}; - DrawingEngine drawing_engine_get_type() { auto context = GetContext(); diff --git a/src/openrct2/drawing/NewDrawing.h b/src/openrct2/drawing/NewDrawing.h index 16ff47ca81..09edb45699 100644 --- a/src/openrct2/drawing/NewDrawing.h +++ b/src/openrct2/drawing/NewDrawing.h @@ -16,8 +16,6 @@ struct DrawPixelInfo; enum class DrawingEngine : int32_t; -extern StringId DrawingEngineStringIds[3]; - DrawingEngine drawing_engine_get_type(); bool DrawingEngineRequiresNewWindow(DrawingEngine srcEngine, DrawingEngine dstEngine); void DrawingEngineInit();