diff --git a/premake5.lua b/premake5.lua index 065463a48..8e304478e 100644 --- a/premake5.lua +++ b/premake5.lua @@ -243,6 +243,7 @@ solution("xenia") include("src/xenia/gpu/null") include("src/xenia/gpu/vk") include("src/xenia/gpu/vulkan") + include("src/xenia/helper/sdl") include("src/xenia/hid") include("src/xenia/hid/nop") include("src/xenia/hid/sdl") diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index fb316f840..02eb180ce 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -34,6 +34,7 @@ project("xenia-app") "xenia-gpu-null", "xenia-gpu-vk", "xenia-gpu-vulkan", + "xenia-helper-sdl", "xenia-hid", "xenia-hid-nop", "xenia-hid-sdl", diff --git a/src/xenia/apu/sdl/premake5.lua b/src/xenia/apu/sdl/premake5.lua index 995b128dd..8f0e9ab61 100644 --- a/src/xenia/apu/sdl/premake5.lua +++ b/src/xenia/apu/sdl/premake5.lua @@ -7,8 +7,9 @@ project("xenia-apu-sdl") kind("StaticLib") language("C++") links({ - "xenia-base", "xenia-apu", + "xenia-base", + "xenia-helper-sdl", "SDL2", }) defines({ diff --git a/src/xenia/apu/sdl/sdl_audio_driver.cc b/src/xenia/apu/sdl/sdl_audio_driver.cc index c7fe9bd42..a16e9e5d1 100644 --- a/src/xenia/apu/sdl/sdl_audio_driver.cc +++ b/src/xenia/apu/sdl/sdl_audio_driver.cc @@ -13,9 +13,7 @@ #include "xenia/apu/apu_flags.h" #include "xenia/base/logging.h" -#if XE_PLATFORM_WIN32 -#include "xenia/base/platform_win.h" -#endif // XE_PLATFORM_WIN32 +#include "xenia/helper/sdl/sdl_helper.h" namespace xe { namespace apu { @@ -31,7 +29,6 @@ SDLAudioDriver::~SDLAudioDriver() { }; bool SDLAudioDriver::Initialize() { - XELOG_SDL_INIT() SDL_version ver = {}; SDL_GetVersion(&ver); if ((ver.major < 2) || (ver.major == 2 && ver.minor == 0 && ver.patch < 8)) { @@ -41,6 +38,9 @@ bool SDLAudioDriver::Initialize() { ver.major, ver.minor, ver.patch); } + if (!xe::helper::sdl::SDLHelper::Prepare()) { + return false; + } if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { return false; } diff --git a/src/xenia/base/logging.h b/src/xenia/base/logging.h index 32f31709a..d9fde04a0 100644 --- a/src/xenia/base/logging.h +++ b/src/xenia/base/logging.h @@ -119,40 +119,6 @@ void XELOGFS(const char* format, const Args&... args) { xe::logging::AppendLogLineFormat(xe::LogLevel::Info, 'F', format, args...); } -// Redirect SDL_Log* output (internal library stuff) to our log system. -// Can't execute this code here without linking SDL2 into all projects. -// Use this macro everywhere SDL_InitSubSystem() is called. -#define XELOG_SDL_INIT() \ - { \ - SDL_LogSetOutputFunction( \ - [](void* userdata, int category, SDL_LogPriority priority, \ - const char* message) { \ - const char* msg_fmt = "SDL: {}"; \ - switch (priority) { \ - case SDL_LOG_PRIORITY_VERBOSE: \ - case SDL_LOG_PRIORITY_DEBUG: \ - XELOGD(msg_fmt, message); \ - break; \ - case SDL_LOG_PRIORITY_INFO: \ - XELOGI(msg_fmt, message); \ - break; \ - case SDL_LOG_PRIORITY_WARN: \ - XELOGW(msg_fmt, message); \ - break; \ - case SDL_LOG_PRIORITY_ERROR: \ - case SDL_LOG_PRIORITY_CRITICAL: \ - XELOGE(msg_fmt, message); \ - break; \ - default: \ - XELOGI(msg_fmt, message); \ - assert_always("SDL: Unknown log priority"); \ - break; \ - } \ - }, \ - nullptr); \ - SDL_LogSetAllPriority(SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); \ - } - #else #define XELOGDUMMY \ @@ -169,8 +135,6 @@ void XELOGFS(const char* format, const Args&... args) { #define XELOGKERNEL(...) XELOGDUMMY #define XELOGFS(...) XELOGDUMMY -#define XELOG_SDL_INIT() XELOGDUMMY - #undef XELOGDUMMY #endif // ENABLE_LOGGING diff --git a/src/xenia/helper/sdl/premake5.lua b/src/xenia/helper/sdl/premake5.lua new file mode 100644 index 000000000..fd13bd5aa --- /dev/null +++ b/src/xenia/helper/sdl/premake5.lua @@ -0,0 +1,17 @@ +project_root = "../../../.." +include(project_root.."/tools/build") + +group("src") +project("xenia-helper-sdl") + uuid("84b00ad3-fba3-4561-96c9-1f9993b14c9c") + kind("StaticLib") + language("C++") + links({ + "SDL2", + }) + defines({ + }) + includedirs({ + }) + local_platform_files() + sdl2_include() diff --git a/src/xenia/helper/sdl/sdl_helper.cc b/src/xenia/helper/sdl/sdl_helper.cc new file mode 100644 index 000000000..921df4517 --- /dev/null +++ b/src/xenia/helper/sdl/sdl_helper.cc @@ -0,0 +1,81 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/helper/sdl/sdl_helper.h" + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" + +namespace xe { +namespace helper { +namespace sdl { +bool SDLHelper::is_prepared_ = false; + +bool SDLHelper::Prepare() { + if (is_prepared_) { + return true; + } + is_prepared_ = true; + + is_prepared_ &= SetHints(); + is_prepared_ &= RedirectLog(); + + return is_prepared_; +} + +bool SDLHelper::SetHints() { + bool suc = true; + + // SDL calls timeBeginPeriod(1) but xenia sets this to a lower value before + // using NtSetTimerResolution(). Having that value overwritten causes overall + // fps drops. Use override priority as timer resolution should always be + // managed by xenia. https://bugzilla.libsdl.org/show_bug.cgi?id=5104 + suc &= SDL_SetHintWithPriority(SDL_HINT_TIMER_RESOLUTION, "0", + SDL_HINT_OVERRIDE) == SDL_TRUE; + + return suc; +} + +bool SDLHelper::RedirectLog() { + // Redirect SDL_Log* output (internal library stuff) to our log system. + SDL_LogSetOutputFunction( + [](void* userdata, int category, SDL_LogPriority priority, + const char* message) { + const char* msg_fmt = "SDL: {}"; + switch (priority) { + case SDL_LOG_PRIORITY_VERBOSE: + case SDL_LOG_PRIORITY_DEBUG: + XELOGD(msg_fmt, message); + break; + case SDL_LOG_PRIORITY_INFO: + XELOGI(msg_fmt, message); + break; + case SDL_LOG_PRIORITY_WARN: + XELOGW(msg_fmt, message); + break; + case SDL_LOG_PRIORITY_ERROR: + case SDL_LOG_PRIORITY_CRITICAL: + XELOGE(msg_fmt, message); + break; + default: + XELOGI(msg_fmt, message); + assert_always("SDL: Unknown log priority"); + break; + } + }, + nullptr); + // SDL itself isn't that talkative. Additionally to this settings there are + // hints that can be switched on to output additional internal logging + // information. + SDL_LogSetAllPriority(SDL_LogPriority::SDL_LOG_PRIORITY_VERBOSE); + return true; +} +} // namespace sdl +} // namespace helper +} // namespace xe diff --git a/src/xenia/helper/sdl/sdl_helper.h b/src/xenia/helper/sdl/sdl_helper.h new file mode 100644 index 000000000..43504be20 --- /dev/null +++ b/src/xenia/helper/sdl/sdl_helper.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2020 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_HELPER_SDL_SDL_HELPER_H_ +#define XENIA_HELPER_SDL_SDL_HELPER_H_ + +#include "SDL.h" + +namespace xe { +namespace helper { +namespace sdl { +// This helper class exists to independently use SDL from different parts of +// xenia. +class SDLHelper { + public: + // To configure the SDL library for use in xenia call this function before + // SDL_InitSubSystem() is called. + static bool Prepare(); + static bool IsPrepared() { return is_prepared_; } + + private: + static bool SetHints(); + static bool RedirectLog(); + + private: + static bool is_prepared_; +}; +} // namespace sdl +} // namespace helper +} // namespace xe + +#endif // XENIA_HELPER_SDL_SDL_HELPER_H_ \ No newline at end of file diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index e0148d9c7..152887e2b 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -24,6 +24,7 @@ project("xenia-hid-demo") "imgui", "volk", "xenia-base", + "xenia-helper-sdl", "xenia-hid", "xenia-hid-nop", "xenia-hid-sdl", diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index fa3057cfd..470892588 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -18,6 +18,7 @@ #include "xenia/base/clock.h" #include "xenia/base/cvar.h" #include "xenia/base/logging.h" +#include "xenia/helper/sdl/sdl_helper.h" #include "xenia/hid/hid_flags.h" #include "xenia/ui/window.h" @@ -58,7 +59,6 @@ SDLInputDriver::~SDLInputDriver() { } X_STATUS SDLInputDriver::Setup() { - XELOG_SDL_INIT() if (!TestSDLVersion()) { return X_STATUS_UNSUCCESSFUL; } @@ -66,6 +66,9 @@ X_STATUS SDLInputDriver::Setup() { // SDL_PumpEvents should only be run in the thread that initialized SDL - we // are hijacking the window loop thread for that. window_->loop()->PostSynchronous([&]() { + if (!xe::helper::sdl::SDLHelper::Prepare()) { + return; + } // Initialize the event system early, so we catch device events for already // connected controllers. if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {