SDLInputSource: Centralize SDL subsystem loading

pull/3794/head
Stenzek 2 weeks ago
parent 0fbd997d4d
commit 0206d926f3
No known key found for this signature in database

@ -17,6 +17,7 @@
#include "common/error.h"
#include "common/log.h"
#include <atomic>
#include <utility>
LOG_CHANNEL(DynamicLibrary);
@ -59,6 +60,8 @@ static constexpr int SPIRV_CROSS_MAJOR_VERSION = SPVC_C_API_VERSION_MAJOR;
namespace {
struct Locals
{
~Locals();
DynamicLibrary freetype_library;
std::once_flag freetype_init_flag;
DynamicLibrary plutosvg_library;
@ -73,6 +76,7 @@ struct Locals
std::once_flag libzip_init_flag;
DynamicLibrary sdl_library;
std::once_flag sdl_init_flag;
std::atomic<SDL_InitFlags> sdl_init_subsystems{0};
DynamicLibrary sqlite_library;
std::once_flag sqlite_init_flag;
DynamicLibrary shaderc_library;
@ -80,10 +84,6 @@ struct Locals
shaderc_compiler_t shaderc_compiler;
DynamicLibrary spirv_cross_library;
std::once_flag spirv_cross_init_flag;
#if defined(_DEBUG) || defined(_DEVEL)
~Locals();
#endif
};
} // namespace
@ -99,14 +99,14 @@ DynShaderc g_dyn_shaderc;
DynSpirvCross g_dyn_spirv_cross;
static Locals s_locals;
#if defined(_DEBUG) || defined(_DEVEL)
Locals::~Locals()
{
DebugAssert(!s_locals.shaderc_compiler);
}
#endif
// Quit any persistent SDL subsystems before unloading the library.
if (const SDL_InitFlags active_subsystems = s_locals.sdl_init_subsystems.load(std::memory_order_acquire))
g_dyn_sdl.SDL_QuitSubSystem(active_subsystems);
}
static bool LoadDynLib(const char* libname, int major_version, DynamicLibrary& dynlib, std::once_flag& once_flag,
std::span<const DynamicLibrary::SymbolTable> symbols, Error* const error,
@ -273,7 +273,7 @@ static bool SDLLoadCallback(Error* const error)
return true;
}
bool DynSDL::Open(Error* error)
bool DynSDL::Open(Error* const error)
{
if (s_locals.sdl_library.IsOpen()) [[likely]]
return true;
@ -282,6 +282,31 @@ bool DynSDL::Open(Error* error)
SDLLoadCallback);
}
bool DynSDL::InitSubSystem(SDL_InitFlags flags, Error* const error)
{
// anything added?
const SDL_InitFlags prev_subsystems = s_locals.sdl_init_subsystems.fetch_or(flags, std::memory_order_acq_rel);
const SDL_InitFlags subsystems_to_init = (flags & ~prev_subsystems);
if (subsystems_to_init == 0 || SDL_InitSubSystem(subsystems_to_init))
return true;
s_locals.sdl_init_subsystems.fetch_and(~subsystems_to_init, std::memory_order_acq_rel);
const char* sdl_error = SDL_GetError();
Error::SetStringFmt(error, "SDL_InitSubSystem(0x{:08X}) failed: {}", static_cast<u32>(subsystems_to_init),
sdl_error ? sdl_error : "");
return false;
}
void DynSDL::QuitSubSystem(SDL_InitFlags flags)
{
// anything removed?
const SDL_InitFlags prev_subsystems = s_locals.sdl_init_subsystems.fetch_and(~flags, std::memory_order_acq_rel);
const SDL_InitFlags subsystems_to_release = (flags & prev_subsystems);
if (subsystems_to_release != 0)
SDL_QuitSubSystem(subsystems_to_release);
}
static const DynamicLibrary::SymbolTable s_shaderc_symbols[] = {
#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_shaderc.F},
DYN_SHADERC_FUNCTIONS(RESOLVE_SYMBOL)

@ -75,7 +75,9 @@ struct DynSDL
DYN_SDL_FUNCTIONS(ADD_FUNC)
#undef ADD_FUNC
bool Open(Error* error);
bool Open(Error* const error);
bool InitSubSystem(SDL_InitFlags flags, Error* const error);
void QuitSubSystem(SDL_InitFlags flags);
};
extern DynSDL g_dyn_sdl;

@ -33,28 +33,6 @@ protected:
};
} // namespace
static bool InitializeSDLAudio(Error* error)
{
static bool initialized = false;
if (initialized)
return true;
if (!g_dyn_sdl.Open(error))
return false;
// May as well keep it alive until the process exits.
if (!g_dyn_sdl.SDL_InitSubSystem(SDL_INIT_AUDIO))
{
Error::SetStringFmt(error, "SDL_InitSubSystem(SDL_INIT_AUDIO) failed: {}", g_dyn_sdl.SDL_GetError());
return false;
}
std::atexit([]() { g_dyn_sdl.SDL_QuitSubSystem(SDL_INIT_AUDIO); });
initialized = true;
return true;
}
SDLAudioStream::SDLAudioStream(AudioStreamSource* source, u32 channels) : m_source(source), m_channels(channels)
{
}
@ -129,7 +107,8 @@ std::unique_ptr<AudioStream> AudioStream::CreateSDLAudioStream(u32 sample_rate,
bool output_latency_minimal, AudioStreamSource* source,
bool auto_start, Error* error)
{
if (!InitializeSDLAudio(error))
// May as well keep it alive until the process exits.
if (!g_dyn_sdl.Open(error) || !g_dyn_sdl.InitSubSystem(SDL_INIT_AUDIO, error))
return {};
std::unique_ptr<SDLAudioStream> stream = std::make_unique<SDLAudioStream>(source, channels);

@ -582,15 +582,13 @@ void SDLInputSource::SetHints()
bool SDLInputSource::InitializeSubsystem()
{
if (!g_dyn_sdl.SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC))
if (Error error; !g_dyn_sdl.InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC, &error))
{
ERROR_LOG("SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC) failed");
ERROR_LOG(error.GetDescription());
return false;
}
// we should open the controllers as the connected events come in, so no need to do any more here
m_sdl_subsystem_initialized = true;
int mapping_count = 0;
g_dyn_sdl.SDL_free(g_dyn_sdl.SDL_GetGamepadMappings(&mapping_count));
INFO_LOG("{} controller mappings are loaded.", mapping_count);
@ -603,11 +601,7 @@ void SDLInputSource::ShutdownSubsystem()
while (!m_controllers.empty())
CloseDevice(m_controllers.begin()->joystick_id);
if (m_sdl_subsystem_initialized)
{
g_dyn_sdl.SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC);
m_sdl_subsystem_initialized = false;
}
g_dyn_sdl.QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC);
}
void SDLInputSource::PollEvents()

Loading…
Cancel
Save