[SDL] Add global helper to setup the library.

Call to SDLHelper::Prepare() is needed before first SDL_InitSubSystem().
- Sets hints (SDL configuration vars).
- Configures logging.
This commit is contained in:
Joel Linn 2020-04-23 12:14:53 +02:00 committed by Rick Gibbed
parent 5463798631
commit 6267c73c4c
10 changed files with 149 additions and 42 deletions

View File

@ -243,6 +243,7 @@ solution("xenia")
include("src/xenia/gpu/null") include("src/xenia/gpu/null")
include("src/xenia/gpu/vk") include("src/xenia/gpu/vk")
include("src/xenia/gpu/vulkan") include("src/xenia/gpu/vulkan")
include("src/xenia/helper/sdl")
include("src/xenia/hid") include("src/xenia/hid")
include("src/xenia/hid/nop") include("src/xenia/hid/nop")
include("src/xenia/hid/sdl") include("src/xenia/hid/sdl")

View File

@ -34,6 +34,7 @@ project("xenia-app")
"xenia-gpu-null", "xenia-gpu-null",
"xenia-gpu-vk", "xenia-gpu-vk",
"xenia-gpu-vulkan", "xenia-gpu-vulkan",
"xenia-helper-sdl",
"xenia-hid", "xenia-hid",
"xenia-hid-nop", "xenia-hid-nop",
"xenia-hid-sdl", "xenia-hid-sdl",

View File

@ -7,8 +7,9 @@ project("xenia-apu-sdl")
kind("StaticLib") kind("StaticLib")
language("C++") language("C++")
links({ links({
"xenia-base",
"xenia-apu", "xenia-apu",
"xenia-base",
"xenia-helper-sdl",
"SDL2", "SDL2",
}) })
defines({ defines({

View File

@ -13,9 +13,7 @@
#include "xenia/apu/apu_flags.h" #include "xenia/apu/apu_flags.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#if XE_PLATFORM_WIN32 #include "xenia/helper/sdl/sdl_helper.h"
#include "xenia/base/platform_win.h"
#endif // XE_PLATFORM_WIN32
namespace xe { namespace xe {
namespace apu { namespace apu {
@ -31,7 +29,6 @@ SDLAudioDriver::~SDLAudioDriver() {
}; };
bool SDLAudioDriver::Initialize() { bool SDLAudioDriver::Initialize() {
XELOG_SDL_INIT()
SDL_version ver = {}; SDL_version ver = {};
SDL_GetVersion(&ver); SDL_GetVersion(&ver);
if ((ver.major < 2) || (ver.major == 2 && ver.minor == 0 && ver.patch < 8)) { 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); ver.major, ver.minor, ver.patch);
} }
if (!xe::helper::sdl::SDLHelper::Prepare()) {
return false;
}
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
return false; return false;
} }

View File

@ -119,40 +119,6 @@ void XELOGFS(const char* format, const Args&... args) {
xe::logging::AppendLogLineFormat(xe::LogLevel::Info, 'F', format, 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 #else
#define XELOGDUMMY \ #define XELOGDUMMY \
@ -169,8 +135,6 @@ void XELOGFS(const char* format, const Args&... args) {
#define XELOGKERNEL(...) XELOGDUMMY #define XELOGKERNEL(...) XELOGDUMMY
#define XELOGFS(...) XELOGDUMMY #define XELOGFS(...) XELOGDUMMY
#define XELOG_SDL_INIT() XELOGDUMMY
#undef XELOGDUMMY #undef XELOGDUMMY
#endif // ENABLE_LOGGING #endif // ENABLE_LOGGING

View File

@ -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()

View File

@ -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

View File

@ -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_

View File

@ -24,6 +24,7 @@ project("xenia-hid-demo")
"imgui", "imgui",
"volk", "volk",
"xenia-base", "xenia-base",
"xenia-helper-sdl",
"xenia-hid", "xenia-hid",
"xenia-hid-nop", "xenia-hid-nop",
"xenia-hid-sdl", "xenia-hid-sdl",

View File

@ -18,6 +18,7 @@
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/cvar.h" #include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/helper/sdl/sdl_helper.h"
#include "xenia/hid/hid_flags.h" #include "xenia/hid/hid_flags.h"
#include "xenia/ui/window.h" #include "xenia/ui/window.h"
@ -58,7 +59,6 @@ SDLInputDriver::~SDLInputDriver() {
} }
X_STATUS SDLInputDriver::Setup() { X_STATUS SDLInputDriver::Setup() {
XELOG_SDL_INIT()
if (!TestSDLVersion()) { if (!TestSDLVersion()) {
return X_STATUS_UNSUCCESSFUL; 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 // SDL_PumpEvents should only be run in the thread that initialized SDL - we
// are hijacking the window loop thread for that. // are hijacking the window loop thread for that.
window_->loop()->PostSynchronous([&]() { window_->loop()->PostSynchronous([&]() {
if (!xe::helper::sdl::SDLHelper::Prepare()) {
return;
}
// Initialize the event system early, so we catch device events for already // Initialize the event system early, so we catch device events for already
// connected controllers. // connected controllers.
if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) { if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {