diff --git a/src/util/dyn_libjpeg.h b/src/util/dyn_libjpeg.h new file mode 100644 index 000000000..6ae1d7f00 --- /dev/null +++ b/src/util/dyn_libjpeg.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin +// SPDX-License-Identifier: CC-BY-NC-ND-4.0 + +#pragma once + +#include + +class Error; + +#define DYN_LIBJPEG_FUNCTIONS(X) \ + X(jpeg_CreateDecompress) \ + X(jpeg_CreateCompress) \ + X(jpeg_destroy_decompress) \ + X(jpeg_destroy_compress) \ + X(jpeg_std_error) \ + X(jpeg_read_header) \ + X(jpeg_start_decompress) \ + X(jpeg_read_scanlines) \ + X(jpeg_finish_decompress) \ + X(jpeg_mem_src) \ + X(jpeg_resync_to_restart) \ + X(jpeg_set_defaults) \ + X(jpeg_set_quality) \ + X(jpeg_start_compress) \ + X(jpeg_write_scanlines) \ + X(jpeg_finish_compress) + +struct DynLibJPEG +{ +#define ADD_FUNC(F) decltype(&::F) F; + DYN_LIBJPEG_FUNCTIONS(ADD_FUNC) +#undef ADD_FUNC + + bool Open(Error* error); +}; + +extern DynLibJPEG g_dyn_libjpeg; diff --git a/src/util/dyn_libs.cpp b/src/util/dyn_libs.cpp index d4c790b19..2a69400de 100644 --- a/src/util/dyn_libs.cpp +++ b/src/util/dyn_libs.cpp @@ -2,45 +2,110 @@ // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "dyn_freetype.h" +#include "dyn_libjpeg.h" +#include "dyn_libpng.h" +#include "dyn_libwebp.h" #include "dyn_plutosvg.h" +#include "dyn_sdl.h" +#include "dyn_shaderc.h" +#include "dyn_spirv_cross.h" +#include "dyn_sqlite.h" +#include "common/assert.h" #include "common/dynamic_library.h" #include "common/error.h" #include "common/log.h" +#include + LOG_CHANNEL(DynamicLibrary); +// Ensure it's in .bss static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); +static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); // Because of course friggin linux is different... #ifdef _WIN32 static constexpr int FREETYPE_MAJOR_VERSION = -1; static constexpr int PLUTOSVG_MAJOR_VERSION = -1; +static constexpr int LIBPNG_MAJOR_VERSION = -1; +static constexpr int LIBJPEG_MAJOR_VERSION = -1; +static constexpr int LIBWEBP_MAJOR_VERSION = -1; +static constexpr int LIBSDL_MAJOR_VERSION = -1; +static constexpr int SQLITE_MAJOR_VERSION = -1; +static constexpr int SPIRV_CROSS_MAJOR_VERSION = -1; #else static constexpr int FREETYPE_MAJOR_VERSION = 6; static constexpr int PLUTOSVG_MAJOR_VERSION = 0; +static constexpr int LIBPNG_MAJOR_VERSION = 16; +static constexpr int LIBJPEG_MAJOR_VERSION = 62; +static constexpr int LIBWEBP_MAJOR_VERSION = 7; +static constexpr int LIBSDL_MAJOR_VERSION = 0; +static constexpr int SQLITE_MAJOR_VERSION = 3; +static constexpr int SPIRV_CROSS_MAJOR_VERSION = SPVC_C_API_VERSION_MAJOR; #endif namespace { struct Locals { - // Dynamic libraries DynamicLibrary freetype_library; std::once_flag freetype_init_flag; DynamicLibrary plutosvg_library; std::once_flag plutosvg_init_flag; + DynamicLibrary libjpeg_library; + std::once_flag libjpeg_init_flag; + DynamicLibrary libpng_library; + std::once_flag libpng_init_flag; + DynamicLibrary libwebp_library; + std::once_flag libwebp_init_flag; + DynamicLibrary sdl_library; + std::once_flag sdl_init_flag; + DynamicLibrary sqlite_library; + std::once_flag sqlite_init_flag; + DynamicLibrary shaderc_library; + std::once_flag shaderc_init_flag; + shaderc_compiler_t shaderc_compiler; + DynamicLibrary spirv_cross_library; + std::once_flag spirv_cross_init_flag; + +#if defined(_DEBUG) || defined(_DEVEL) + ~Locals(); +#endif }; } // namespace DynFreeType g_dyn_freetype; DynPlutoSvg g_dyn_plutosvg; +DynLibJPEG g_dyn_libjpeg; +DynLibWebP g_dyn_libwebp; +DynLibPNG g_dyn_libpng; +DynSDL g_dyn_sdl; +DynSqlite g_dyn_sqlite; +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 + static bool LoadDynLib(const char* libname, int major_version, DynamicLibrary& dynlib, std::once_flag& once_flag, - std::span symbols, Error* const error) + std::span symbols, Error* const error, + bool (*extra_loader)(Error* const) = nullptr) { - std::call_once(once_flag, [&libname, &major_version, &dynlib, &symbols, error]() { + std::call_once(once_flag, [&libname, &major_version, &dynlib, &symbols, extra_loader, error]() { Error lerror; DynamicLibrary lib; if (!lib.Open(DynamicLibrary::GetVersionedFilename(libname, major_version).c_str(), &lerror) || @@ -51,6 +116,12 @@ static bool LoadDynLib(const char* libname, int major_version, DynamicLibrary& d return; } + if (extra_loader && !extra_loader(error)) + { + DynamicLibrary::ClearSymbols(symbols.data(), symbols.size()); + return; + } + dynlib = std::move(lib); }); @@ -86,3 +157,155 @@ bool DynPlutoSvg::Open(Error* const error) return LoadDynLib("plutosvg", PLUTOSVG_MAJOR_VERSION, s_locals.plutosvg_library, s_locals.plutosvg_init_flag, s_plutosvg_symbols, error); } + +static const DynamicLibrary::SymbolTable s_libpng_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_libpng.F}, + DYN_LIBPNG_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; + +bool DynLibPNG::Open(Error* const error) +{ + if (s_locals.libpng_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("libpng16", LIBPNG_MAJOR_VERSION, s_locals.libpng_library, s_locals.libpng_init_flag, + s_libpng_symbols, error); +} + +static const DynamicLibrary::SymbolTable s_libjpeg_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_libjpeg.F}, + DYN_LIBJPEG_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; + +bool DynLibJPEG::Open(Error* const error) +{ + if (s_locals.libjpeg_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("jpeg", LIBJPEG_MAJOR_VERSION, s_locals.libjpeg_library, s_locals.libjpeg_init_flag, + s_libjpeg_symbols, error); +} + +static const DynamicLibrary::SymbolTable s_libwebp_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_libwebp.F}, + DYN_LIBWEBP_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; + +bool DynLibWebP::Open(Error* const error) +{ + if (s_locals.libwebp_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("webp", LIBWEBP_MAJOR_VERSION, s_locals.libwebp_library, s_locals.libwebp_init_flag, + s_libwebp_symbols, error); +} + +static const DynamicLibrary::SymbolTable s_sdl_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_sdl.F}, + DYN_SDL_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; + +static const DynamicLibrary::SymbolTable s_sqlite_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_sqlite.F}, + DYN_SQLITE_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; + +bool DynSqlite::Open(Error* error) +{ + if (s_locals.sqlite_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("sqlite3", SQLITE_MAJOR_VERSION, s_locals.sqlite_library, s_locals.sqlite_init_flag, + s_sqlite_symbols, error); +} + +static void SDLLogCallback(void* userdata, int category, SDL_LogPriority priority, const char* message) +{ + static constexpr Log::Level priority_map[SDL_LOG_PRIORITY_COUNT] = { + Log::Level::Debug, // SDL_LOG_PRIORITY_INVALID + Log::Level::Trace, // SDL_LOG_PRIORITY_TRACE + Log::Level::Verbose, // SDL_LOG_PRIORITY_VERBOSE + Log::Level::Debug, // SDL_LOG_PRIORITY_DEBUG + Log::Level::Info, // SDL_LOG_PRIORITY_INFO + Log::Level::Warning, // SDL_LOG_PRIORITY_WARN + Log::Level::Error, // SDL_LOG_PRIORITY_ERROR + Log::Level::Error, // SDL_LOG_PRIORITY_CRITICAL + }; + + GENERIC_LOG(Log::Channel::SDL, priority_map[priority], Log::Color::Default, message); +} + +static bool SDLLoadCallback(Error* const error) +{ + g_dyn_sdl.SDL_SetLogOutputFunction(SDLLogCallback, nullptr); +#if defined(_DEBUG) || defined(_DEVEL) + g_dyn_sdl.SDL_SetLogPriorities(SDL_LOG_PRIORITY_DEBUG); +#else + g_dyn_sdl.SDL_SetLogPriorities(SDL_LOG_PRIORITY_INFO); +#endif + return true; +} + +bool DynSDL::Open(Error* error) +{ + if (s_locals.sdl_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("SDL3", LIBSDL_MAJOR_VERSION, s_locals.sdl_library, s_locals.sdl_init_flag, s_sdl_symbols, error, + SDLLoadCallback); +} + +static const DynamicLibrary::SymbolTable s_shaderc_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_shaderc.F}, + DYN_SHADERC_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; + +bool DynShaderc::Open(Error* const error) +{ + if (s_locals.shaderc_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("shaderc_shared", -1, s_locals.shaderc_library, s_locals.shaderc_init_flag, s_shaderc_symbols, + error, [](Error* const error) { + g_dyn_shaderc.compiler = g_dyn_shaderc.shaderc_compiler_initialize(); + if (!g_dyn_shaderc.compiler) + { + ERROR_LOG("shaderc_compiler_initialize() failed"); + Error::SetStringView(error, "shaderc_compiler_initialize() failed"); + return false; + } + + return true; + }); +} + +void DynShaderc::Close() +{ + if (compiler) + shaderc_compiler_release(std::exchange(compiler, nullptr)); +} + +// clang-format off +static const DynamicLibrary::SymbolTable s_spirv_cross_symbols[] = { +#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_spirv_cross.F}, + DYN_SPIRV_CROSS_FUNCTIONS(RESOLVE_SYMBOL) + DYN_SPIRV_CROSS_HLSL_FUNCTIONS(RESOLVE_SYMBOL) + DYN_SPIRV_CROSS_MSL_FUNCTIONS(RESOLVE_SYMBOL) +#undef RESOLVE_SYMBOL +}; +// clang-format on + +bool DynSpirvCross::Open(Error* const error) +{ + if (s_locals.spirv_cross_library.IsOpen()) [[likely]] + return true; + + return LoadDynLib("spirv-cross-c-shared", SPIRV_CROSS_MAJOR_VERSION, s_locals.spirv_cross_library, + s_locals.spirv_cross_init_flag, s_spirv_cross_symbols, error); +} diff --git a/src/util/dyn_libwebp.h b/src/util/dyn_libwebp.h new file mode 100644 index 000000000..0d46def7b --- /dev/null +++ b/src/util/dyn_libwebp.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin +// SPDX-License-Identifier: CC-BY-NC-ND-4.0 + +#pragma once + +#include +#include + +class Error; + +#define DYN_LIBWEBP_FUNCTIONS(X) \ + X(WebPGetInfo) \ + X(WebPDecodeRGBAInto) \ + X(WebPEncodeRGBA) \ + X(WebPFree) + +struct DynLibWebP +{ +#define ADD_FUNC(F) decltype(&::F) F; + DYN_LIBWEBP_FUNCTIONS(ADD_FUNC) +#undef ADD_FUNC + + bool Open(Error* error); +}; + +extern DynLibWebP g_dyn_libwebp; diff --git a/src/util/dyn_shaderc.h b/src/util/dyn_shaderc.h index 033984886..c09da92a2 100644 --- a/src/util/dyn_shaderc.h +++ b/src/util/dyn_shaderc.h @@ -33,6 +33,7 @@ struct DynShaderc shaderc_compiler_t compiler; bool Open(Error* error); + void Close(); }; extern DynShaderc g_dyn_shaderc; diff --git a/src/util/dyn_spirv_cross.h b/src/util/dyn_spirv_cross.h index af7f4f174..fe6fcb052 100644 --- a/src/util/dyn_spirv_cross.h +++ b/src/util/dyn_spirv_cross.h @@ -7,7 +7,7 @@ class Error; -#define SPIRV_CROSS_FUNCTIONS(X) \ +#define DYN_SPIRV_CROSS_FUNCTIONS(X) \ X(spvc_context_create) \ X(spvc_context_destroy) \ X(spvc_context_set_error_callback) \ @@ -34,24 +34,24 @@ class Error; X(spvc_resources_get_resource_list_for_type) #ifdef _WIN32 -#define SPIRV_CROSS_HLSL_FUNCTIONS(X) \ +#define DYN_SPIRV_CROSS_HLSL_FUNCTIONS(X) \ X(spvc_compiler_hlsl_add_resource_binding) \ X(spvc_compiler_hlsl_add_vertex_attribute_remap) #else -#define SPIRV_CROSS_HLSL_FUNCTIONS(X) +#define DYN_SPIRV_CROSS_HLSL_FUNCTIONS(X) #endif #ifdef __APPLE__ -#define SPIRV_CROSS_MSL_FUNCTIONS(X) X(spvc_compiler_msl_add_resource_binding) +#define DYN_SPIRV_CROSS_MSL_FUNCTIONS(X) X(spvc_compiler_msl_add_resource_binding) #else -#define SPIRV_CROSS_MSL_FUNCTIONS(X) +#define DYN_SPIRV_CROSS_MSL_FUNCTIONS(X) #endif struct DynSpirvCross { #define ADD_FUNC(F) decltype(&::F) F; - SPIRV_CROSS_FUNCTIONS(ADD_FUNC) - SPIRV_CROSS_HLSL_FUNCTIONS(ADD_FUNC) - SPIRV_CROSS_MSL_FUNCTIONS(ADD_FUNC) + DYN_SPIRV_CROSS_FUNCTIONS(ADD_FUNC) + DYN_SPIRV_CROSS_HLSL_FUNCTIONS(ADD_FUNC) + DYN_SPIRV_CROSS_MSL_FUNCTIONS(ADD_FUNC) #undef ADD_FUNC bool Open(Error* error); diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 718f9d490..6ae3df09d 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -11,7 +11,6 @@ #include "shadergen.h" #include "common/assert.h" -#include "common/dynamic_library.h" #include "common/error.h" #include "common/file_system.h" #include "common/hash_combine.h" @@ -57,20 +56,12 @@ struct Locals std::array pipeline_cache_hash; // Dynamic libraries - DynamicLibrary shaderc_library; - DynamicLibrary spirv_cross_library; - std::once_flag shaderc_init_flag; - std::once_flag spirv_cross_init_flag; + }; } // namespace ALIGN_TO_CACHE_LINE static Locals s_locals; -static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); -static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); -DynShaderc g_dyn_shaderc; -DynSpirvCross g_dyn_spirv_cross; - size_t GPUDevice::s_total_vram_usage = 0; GPUDevice::Statistics GPUDevice::s_stats = {}; @@ -1395,85 +1386,6 @@ std::unique_ptr GPUDevice::CreateDeviceForAPI(RenderAPI api) } } -bool DynShaderc::Open(Error* error) -{ - if (compiler) - return true; - - std::call_once(s_locals.shaderc_init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; - if (!lib.Open(DynamicLibrary::GetVersionedFilename("shaderc_shared").c_str(), error)) - { - ERROR_LOG("Failed to load shaderc: {}", (error ? error : &lerror)->GetDescription()); - Error::AddPrefix(error, "Failed to load shaderc: "); - return; - } - - static const DynamicLibrary::SymbolTable shaderc_symbols[] = { -#define SHADERC_SYMBOL(F) {#F, (void**)&g_dyn_shaderc.F}, - DYN_SHADERC_FUNCTIONS(SHADERC_SYMBOL) -#undef SHADERC_SYMBOL - }; - - if (!lib.ResolveSymbols(shaderc_symbols, error)) - return; - - g_dyn_shaderc.compiler = g_dyn_shaderc.shaderc_compiler_initialize(); - if (!g_dyn_shaderc.compiler) - { - ERROR_LOG("shaderc_compiler_initialize() failed"); - Error::SetStringView(error, "shaderc_compiler_initialize() failed"); - DynamicLibrary::ClearSymbols(shaderc_symbols); - return; - } - - s_locals.shaderc_library = std::move(lib); - }); - - return (compiler != nullptr); -} - -bool DynSpirvCross::Open(Error* error) -{ - if (s_locals.spirv_cross_library.IsOpen()) - return true; - - std::call_once(s_locals.spirv_cross_init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; -#if defined(_WIN32) || defined(__ANDROID__) - // SPVC's build on Windows doesn't spit out a versioned DLL. - const std::string libpath = DynamicLibrary::GetVersionedFilename("spirv-cross-c-shared"); -#else - const std::string libpath = DynamicLibrary::GetVersionedFilename("spirv-cross-c-shared", SPVC_C_API_VERSION_MAJOR); -#endif - if (!lib.Open(libpath.c_str(), error ? error : &lerror)) - { - ERROR_LOG("Failed to load spirv-cross: {}", (error ? error : &lerror)->GetDescription()); - Error::AddPrefix(error, "Failed to load spirv-cross: "); - return; - } - - // clang-format off - static const DynamicLibrary::SymbolTable spirv_cross_symbols[] = { -#define SPIRV_CROSS_SYMBOL(F) {#F, (void**)&g_dyn_spirv_cross.F}, - SPIRV_CROSS_FUNCTIONS(SPIRV_CROSS_SYMBOL) - SPIRV_CROSS_HLSL_FUNCTIONS(SPIRV_CROSS_SYMBOL) - SPIRV_CROSS_MSL_FUNCTIONS(SPIRV_CROSS_SYMBOL) -#undef SPIRV_CROSS_SYMBOL - }; - // clang-format on - - if (!lib.ResolveSymbols(spirv_cross_symbols, std::size(spirv_cross_symbols), error)) - return; - - s_locals.spirv_cross_library = std::move(lib); - }); - - return s_locals.spirv_cross_library.IsOpen(); -} - std::optional> GPUDevice::OptimizeVulkanSpv(const std::span spirv, Error* error) { std::optional> ret; @@ -2060,13 +1972,7 @@ void GPUDevice::UnloadDynamicLibraries() { Assert(!g_gpu_device); - g_dyn_spirv_cross = {}; - s_locals.spirv_cross_library.Close(); - - if (g_dyn_shaderc.compiler) - g_dyn_shaderc.shaderc_compiler_release(g_dyn_shaderc.compiler); - g_dyn_shaderc = {}; - s_locals.shaderc_library.Close(); + g_dyn_shaderc.Close(); #ifdef ENABLE_VULKAN VulkanLoader::DestroyVulkanInstance(); diff --git a/src/util/image.cpp b/src/util/image.cpp index 9befb5751..142f7d721 100644 --- a/src/util/image.cpp +++ b/src/util/image.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "image.h" +#include "dyn_libjpeg.h" #include "dyn_libpng.h" +#include "dyn_libwebp.h" #include "texture_decompress.h" #include "common/assert.h" @@ -21,11 +23,7 @@ #include #include -#include #include -#include -#include -#include #include @@ -37,178 +35,6 @@ LOG_CHANNEL(Image); -#define DYN_LIBJPEG_FUNCTIONS(X) \ - X(jpeg_CreateDecompress) \ - X(jpeg_CreateCompress) \ - X(jpeg_destroy_decompress) \ - X(jpeg_destroy_compress) \ - X(jpeg_std_error) \ - X(jpeg_read_header) \ - X(jpeg_start_decompress) \ - X(jpeg_read_scanlines) \ - X(jpeg_finish_decompress) \ - X(jpeg_mem_src) \ - X(jpeg_resync_to_restart) \ - X(jpeg_set_defaults) \ - X(jpeg_set_quality) \ - X(jpeg_start_compress) \ - X(jpeg_write_scanlines) \ - X(jpeg_finish_compress) - -#define DYN_LIBWEBP_FUNCTIONS(X) \ - X(WebPGetInfo) \ - X(WebPDecodeRGBAInto) \ - X(WebPEncodeRGBA) \ - X(WebPFree) - -namespace { -struct DynLibJPEG -{ - DynamicLibrary library; - std::once_flag init_flag; - -#define ADD_FUNC(F) decltype(&::F) F; - DYN_LIBJPEG_FUNCTIONS(ADD_FUNC) -#undef ADD_FUNC - - bool Open(Error* error); -}; - -struct DynLibWebP -{ - DynamicLibrary library; - std::once_flag init_flag; - -#define ADD_FUNC(F) decltype(&::F) F; - DYN_LIBWEBP_FUNCTIONS(ADD_FUNC) -#undef ADD_FUNC - - bool Open(Error* error); -}; - -struct Locals -{ - DynamicLibrary png_library; - std::once_flag png_init_flag; -}; -} // namespace - -static Locals s_locals; -static DynLibJPEG s_dyn_libjpeg; -static DynLibWebP s_dyn_libwebp; -DynLibPNG g_dyn_libpng; - -bool DynLibPNG::Open(Error* error) -{ - if (s_locals.png_library.IsOpen()) - return true; - - std::call_once(s_locals.png_init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; -#ifdef _WIN32 - static constexpr int lib_major_version = -1; -#else - static constexpr int lib_major_version = 16; -#endif - if (!lib.Open(DynamicLibrary::GetVersionedFilename("libpng16", lib_major_version).c_str(), &lerror)) - { - ERROR_LOG("Failed to load libpng: {}", lerror.GetDescription()); - Error::SetStringFmt(error, "Failed to load libpng: {}", lerror.GetDescription()); - return; - } - - // clang-format off - static const DynamicLibrary::SymbolTable png_symbols[] = { -#define PNG_SYMBOL(F) {#F, (void**)&g_dyn_libpng.F}, - DYN_LIBPNG_FUNCTIONS(PNG_SYMBOL) -#undef PNG_SYMBOL - }; - // clang-format on - - if (!lib.ResolveSymbols(png_symbols, std::size(png_symbols), error)) - return; - - s_locals.png_library = std::move(lib); - }); - - return s_locals.png_library.IsOpen(); -} - -bool DynLibJPEG::Open(Error* error) -{ - if (library.IsOpen()) - return true; - - std::call_once(init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; -#ifdef _WIN32 - static constexpr int lib_major_version = -1; -#else - static constexpr int lib_major_version = 62; -#endif - if (!lib.Open(DynamicLibrary::GetVersionedFilename("jpeg", lib_major_version).c_str(), &lerror)) - { - ERROR_LOG("Failed to load libjpeg: {}", lerror.GetDescription()); - Error::SetStringFmt(error, "Failed to load libjpeg: {}", lerror.GetDescription()); - return; - } - - // clang-format off - static const DynamicLibrary::SymbolTable jpeg_symbols[] = { -#define JPEG_SYMBOL(F) {#F, (void**)&s_dyn_libjpeg.F}, - DYN_LIBJPEG_FUNCTIONS(JPEG_SYMBOL) -#undef JPEG_SYMBOL - }; - // clang-format on - - if (!lib.ResolveSymbols(jpeg_symbols, std::size(jpeg_symbols), error)) - return; - - s_dyn_libjpeg.library = std::move(lib); - }); - - return library.IsOpen(); -} - -bool DynLibWebP::Open(Error* error) -{ - if (library.IsOpen()) - return true; - - std::call_once(init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; -#ifdef _WIN32 - static constexpr int lib_major_version = -1; -#else - static constexpr int lib_major_version = 7; -#endif - if (!lib.Open(DynamicLibrary::GetVersionedFilename("webp", lib_major_version).c_str(), &lerror)) - { - ERROR_LOG("Failed to load libwebp: {}", lerror.GetDescription()); - Error::SetStringFmt(error, "Failed to load libwebp: {}", lerror.GetDescription()); - return; - } - - // clang-format off - static const DynamicLibrary::SymbolTable webp_symbols[] = { -#define WEBP_SYMBOL(F) {#F, (void**)&s_dyn_libwebp.F}, - DYN_LIBWEBP_FUNCTIONS(WEBP_SYMBOL) -#undef WEBP_SYMBOL - }; - // clang-format on - - if (!lib.ResolveSymbols(webp_symbols, std::size(webp_symbols), error)) - return; - - s_dyn_libwebp.library = std::move(lib); - }); - - return library.IsOpen(); -} - static bool PNGBufferLoader(Image* image, std::span data, Error* error); static bool PNGBufferSaver(const Image& image, DynamicHeapArray* data, u8 quality, Error* error); static bool PNGFileLoader(Image* image, std::string_view filename, std::FILE* fp, Error* error); @@ -1394,7 +1220,7 @@ struct JPEGErrorHandler JPEGErrorHandler(Error* errptr_) { - s_dyn_libjpeg.jpeg_std_error(&err); + g_dyn_libjpeg.jpeg_std_error(&err); err.error_exit = &ErrorExit; errptr = errptr_; } @@ -1413,7 +1239,7 @@ struct JPEGErrorHandler template static bool WrapJPEGDecompress(Image* image, Error* error, T setup_func) { - if (!s_dyn_libjpeg.Open(error)) + if (!g_dyn_libjpeg.Open(error)) return false; std::vector scanline; @@ -1424,15 +1250,15 @@ static bool WrapJPEGDecompress(Image* image, Error* error, T setup_func) JPEGErrorHandler errhandler(error); if (fastjmp_set(&errhandler.jbuf) != 0) { - s_dyn_libjpeg.jpeg_destroy_decompress(&info); + g_dyn_libjpeg.jpeg_destroy_decompress(&info); return false; } info.err = &errhandler.err; - s_dyn_libjpeg.jpeg_CreateDecompress(&info, JPEG_LIB_VERSION, sizeof(info)); + g_dyn_libjpeg.jpeg_CreateDecompress(&info, JPEG_LIB_VERSION, sizeof(info)); setup_func(info); - const int herr = s_dyn_libjpeg.jpeg_read_header(&info, TRUE); + const int herr = g_dyn_libjpeg.jpeg_read_header(&info, TRUE); if (herr != JPEG_HEADER_OK) { Error::SetStringFmt(error, "jpeg_read_header() returned {}", herr); @@ -1449,7 +1275,7 @@ static bool WrapJPEGDecompress(Image* image, Error* error, T setup_func) info.out_color_space = JCS_RGB; info.out_color_components = 3; - if (!s_dyn_libjpeg.jpeg_start_decompress(&info)) + if (!g_dyn_libjpeg.jpeg_start_decompress(&info)) { Error::SetStringFmt(error, "jpeg_start_decompress() returned failure"); return false; @@ -1459,7 +1285,7 @@ static bool WrapJPEGDecompress(Image* image, Error* error, T setup_func) if (!image->IsValid()) { Error::SetStringFmt(error, "Image dimensions are too large: {}x{}", info.image_width, info.image_height); - s_dyn_libjpeg.jpeg_destroy_decompress(&info); + g_dyn_libjpeg.jpeg_destroy_decompress(&info); return false; } scanline.resize(static_cast(info.image_width) * 3); @@ -1468,7 +1294,7 @@ static bool WrapJPEGDecompress(Image* image, Error* error, T setup_func) bool result = true; for (u32 y = 0; y < info.image_height; y++) { - if (s_dyn_libjpeg.jpeg_read_scanlines(&info, scanline_buffer, 1) != 1) + if (g_dyn_libjpeg.jpeg_read_scanlines(&info, scanline_buffer, 1) != 1) { Error::SetStringFmt(error, "jpeg_read_scanlines() failed at row {}", y); result = false; @@ -1488,15 +1314,15 @@ static bool WrapJPEGDecompress(Image* image, Error* error, T setup_func) } } - s_dyn_libjpeg.jpeg_finish_decompress(&info); - s_dyn_libjpeg.jpeg_destroy_decompress(&info); + g_dyn_libjpeg.jpeg_finish_decompress(&info); + g_dyn_libjpeg.jpeg_destroy_decompress(&info); return result; } bool JPEGBufferLoader(Image* image, std::span data, Error* error) { return WrapJPEGDecompress(image, error, [data](jpeg_decompress_struct& info) { - s_dyn_libjpeg.jpeg_mem_src(&info, static_cast(data.data()), + g_dyn_libjpeg.jpeg_mem_src(&info, static_cast(data.data()), static_cast(data.size())); }); } @@ -1553,7 +1379,7 @@ bool JPEGFileLoader(Image* image, std::string_view filename, std::FILE* fp, Erro } } }, - .resync_to_restart = s_dyn_libjpeg.jpeg_resync_to_restart, + .resync_to_restart = g_dyn_libjpeg.jpeg_resync_to_restart, .term_source = [](j_decompress_ptr cinfo) {}, }, .fp = fp, @@ -1568,7 +1394,7 @@ bool JPEGFileLoader(Image* image, std::string_view filename, std::FILE* fp, Erro template static bool WrapJPEGCompress(const Image& image, u8 quality, Error* error, T setup_func) { - if (!s_dyn_libjpeg.Open(error)) + if (!g_dyn_libjpeg.Open(error)) return false; std::vector scanline; @@ -1579,12 +1405,12 @@ static bool WrapJPEGCompress(const Image& image, u8 quality, Error* error, T set JPEGErrorHandler errhandler(error); if (fastjmp_set(&errhandler.jbuf) != 0) { - s_dyn_libjpeg.jpeg_destroy_compress(&info); + g_dyn_libjpeg.jpeg_destroy_compress(&info); return false; } info.err = &errhandler.err; - s_dyn_libjpeg.jpeg_CreateCompress(&info, JPEG_LIB_VERSION, sizeof(info)); + g_dyn_libjpeg.jpeg_CreateCompress(&info, JPEG_LIB_VERSION, sizeof(info)); setup_func(info); info.image_width = image.GetWidth(); @@ -1592,9 +1418,9 @@ static bool WrapJPEGCompress(const Image& image, u8 quality, Error* error, T set info.in_color_space = JCS_RGB; info.input_components = 3; - s_dyn_libjpeg.jpeg_set_defaults(&info); - s_dyn_libjpeg.jpeg_set_quality(&info, quality, TRUE); - s_dyn_libjpeg.jpeg_start_compress(&info, TRUE); + g_dyn_libjpeg.jpeg_set_defaults(&info); + g_dyn_libjpeg.jpeg_set_quality(&info, quality, TRUE); + g_dyn_libjpeg.jpeg_start_compress(&info, TRUE); scanline.resize(static_cast(image.GetWidth()) * 3); u8* scanline_buffer[1] = {scanline.data()}; @@ -1614,7 +1440,7 @@ static bool WrapJPEGCompress(const Image& image, u8 quality, Error* error, T set *(dst_ptr++) = Truncate8(rgba >> 16); } - if (s_dyn_libjpeg.jpeg_write_scanlines(&info, scanline_buffer, 1) != 1) + if (g_dyn_libjpeg.jpeg_write_scanlines(&info, scanline_buffer, 1) != 1) { Error::SetStringFmt(error, "jpeg_write_scanlines() failed at row {}", y); result = false; @@ -1622,8 +1448,8 @@ static bool WrapJPEGCompress(const Image& image, u8 quality, Error* error, T set } } - s_dyn_libjpeg.jpeg_finish_compress(&info); - s_dyn_libjpeg.jpeg_destroy_compress(&info); + g_dyn_libjpeg.jpeg_finish_compress(&info); + g_dyn_libjpeg.jpeg_destroy_compress(&info); return result; } @@ -1724,11 +1550,11 @@ bool JPEGFileSaver(const Image& image, std::string_view filename, std::FILE* fp, bool WebPBufferLoader(Image* image, std::span data, Error* error) { - if (!s_dyn_libwebp.Open(error)) + if (!g_dyn_libwebp.Open(error)) return false; int width, height; - if (!s_dyn_libwebp.WebPGetInfo(data.data(), data.size(), &width, &height) || width <= 0 || height <= 0) + if (!g_dyn_libwebp.WebPGetInfo(data.data(), data.size(), &width, &height) || width <= 0 || height <= 0) { Error::SetStringView(error, "WebPGetInfo() failed"); return false; @@ -1741,7 +1567,7 @@ bool WebPBufferLoader(Image* image, std::span data, Error* error) return false; } - if (!s_dyn_libwebp.WebPDecodeRGBAInto(data.data(), data.size(), image->GetPixels(), image->GetStorageSize(), + if (!g_dyn_libwebp.WebPDecodeRGBAInto(data.data(), data.size(), image->GetPixels(), image->GetStorageSize(), image->GetPitch())) { Error::SetStringView(error, "WebPDecodeRGBAInto() failed"); @@ -1754,12 +1580,12 @@ bool WebPBufferLoader(Image* image, std::span data, Error* error) bool WebPBufferSaver(const Image& image, DynamicHeapArray* data, u8 quality, Error* error) { - if (!s_dyn_libwebp.Open(error)) + if (!g_dyn_libwebp.Open(error)) return false; u8* encoded_data; const size_t encoded_size = - s_dyn_libwebp.WebPEncodeRGBA(reinterpret_cast(image.GetPixels()), image.GetWidth(), image.GetHeight(), + g_dyn_libwebp.WebPEncodeRGBA(reinterpret_cast(image.GetPixels()), image.GetWidth(), image.GetHeight(), image.GetPitch(), static_cast(quality), &encoded_data); if (encoded_size == 0) { @@ -1769,7 +1595,7 @@ bool WebPBufferSaver(const Image& image, DynamicHeapArray* data, u8 quality, data->resize(encoded_size); std::memcpy(data->data(), encoded_data, encoded_size); - s_dyn_libwebp.WebPFree(encoded_data); + g_dyn_libwebp.WebPFree(encoded_data); return true; } diff --git a/src/util/sdl_input_source.cpp b/src/util/sdl_input_source.cpp index 48d28c689..d007dd324 100644 --- a/src/util/sdl_input_source.cpp +++ b/src/util/sdl_input_source.cpp @@ -13,7 +13,6 @@ #include "common/assert.h" #include "common/bitutils.h" -#include "common/dynamic_library.h" #include "common/error.h" #include "common/file_system.h" #include "common/gsvector.h" @@ -134,13 +133,6 @@ static constexpr const std::array s_ps_but }}; // clang-format on -struct Locals -{ - // Dynamic libraries - DynamicLibrary sdl_library; - std::once_flag sdl_init_flag; -}; - } // namespace static constexpr std::array s_sdl_hat_direction_names = {{ @@ -223,9 +215,6 @@ static constexpr const SettingInfo s_sdl_advanced_settings_info[] = { #endif }; -DynSDL g_dyn_sdl; -static Locals s_sdl_locals; - static bool IsPSControllerType(u8 type) { return (type >= SDL_GAMEPAD_TYPE_PS3 && type <= SDL_GAMEPAD_TYPE_PS5); @@ -303,68 +292,6 @@ static const char* GetButtonIcon(u8 type, u32 button) return str; } -static void SDLLogCallback(void* userdata, int category, SDL_LogPriority priority, const char* message) -{ - static constexpr Log::Level priority_map[SDL_LOG_PRIORITY_COUNT] = { - Log::Level::Debug, // SDL_LOG_PRIORITY_INVALID - Log::Level::Trace, // SDL_LOG_PRIORITY_TRACE - Log::Level::Verbose, // SDL_LOG_PRIORITY_VERBOSE - Log::Level::Debug, // SDL_LOG_PRIORITY_DEBUG - Log::Level::Info, // SDL_LOG_PRIORITY_INFO - Log::Level::Warning, // SDL_LOG_PRIORITY_WARN - Log::Level::Error, // SDL_LOG_PRIORITY_ERROR - Log::Level::Error, // SDL_LOG_PRIORITY_CRITICAL - }; - - GENERIC_LOG(Log::Channel::SDL, priority_map[priority], Log::Color::Default, message); -} - -bool DynSDL::Open(Error* error) -{ - // Because of course friggin linux is different... -#ifdef _WIN32 - static constexpr int lib_major_version = -1; -#else - static constexpr int lib_major_version = 0; -#endif - - if (s_sdl_locals.sdl_library.IsOpen()) - return true; - - std::call_once(s_sdl_locals.sdl_init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; - if (!lib.Open(DynamicLibrary::GetVersionedFilename("SDL3", lib_major_version).c_str(), &lerror)) - { - ERROR_LOG("Failed to load sqlite: {}", lerror.GetDescription()); - Error::SetStringFmt(error, "Failed to load sqlite: {}", lerror.GetDescription()); - return; - } - - // clang-format off - static const DynamicLibrary::SymbolTable sdl_symbols[] = { -#define SDL_SYMBOL(F) {#F, (void**)&g_dyn_sdl.F}, - DYN_SDL_FUNCTIONS(SDL_SYMBOL) -#undef SDL_SYMBOL - }; - // clang-format on - - if (!lib.ResolveSymbols(sdl_symbols, std::size(sdl_symbols), error)) - return; - - s_sdl_locals.sdl_library = std::move(lib); - - g_dyn_sdl.SDL_SetLogOutputFunction(SDLLogCallback, nullptr); -#if defined(_DEBUG) || defined(_DEVEL) - g_dyn_sdl.SDL_SetLogPriorities(SDL_LOG_PRIORITY_DEBUG); -#else - g_dyn_sdl.SDL_SetLogPriorities(SDL_LOG_PRIORITY_INFO); -#endif - }); - - return s_sdl_locals.sdl_library.IsOpen(); -} - SDLInputSource::SDLInputSource() = default; SDLInputSource::~SDLInputSource() diff --git a/src/util/sqlite_helpers.cpp b/src/util/sqlite_helpers.cpp index 3a2e1597a..0c38017a9 100644 --- a/src/util/sqlite_helpers.cpp +++ b/src/util/sqlite_helpers.cpp @@ -3,7 +3,6 @@ #include "sqlite_helpers.h" -#include "common/dynamic_library.h" #include "common/error.h" #include "common/file_system.h" #include "common/log.h" @@ -14,59 +13,6 @@ LOG_CHANNEL(Host); -namespace { -struct Locals -{ - // Dynamic libraries - DynamicLibrary sqlite_library; - std::once_flag sqlite_init_flag; -}; -} // namespace - -static Locals s_locals; - -static_assert(std::is_trivially_copyable_v && std::is_standard_layout_v); -DynSqlite g_dyn_sqlite; - -bool DynSqlite::Open(Error* error) -{ - // Because of course friggin linux is different... -#ifdef _WIN32 - static constexpr int lib_major_version = -1; -#else - static constexpr int lib_major_version = 3; -#endif - - if (s_locals.sqlite_library.IsOpen()) - return true; - - std::call_once(s_locals.sqlite_init_flag, [&error]() { - Error lerror; - DynamicLibrary lib; - if (!lib.Open(DynamicLibrary::GetVersionedFilename("sqlite3", lib_major_version).c_str(), &lerror)) - { - ERROR_LOG("Failed to load sqlite: {}", lerror.GetDescription()); - Error::SetStringFmt(error, "Failed to load sqlite: {}", lerror.GetDescription()); - return; - } - - // clang-format off - static const DynamicLibrary::SymbolTable sqlite_symbols[] = { -#define SQLITE_SYMBOL(F) {#F, (void**)&g_dyn_sqlite.F}, - DYN_SQLITE_FUNCTIONS(SQLITE_SYMBOL) -#undef SQLITE_SYMBOL - }; - // clang-format on - - if (!lib.ResolveSymbols(sqlite_symbols, std::size(sqlite_symbols), error)) - return; - - s_locals.sqlite_library = std::move(lib); - }); - - return s_locals.sqlite_library.IsOpen(); -} - sqlite3* SQLiteHelpers::OpenAndCheckDatabase(const char* const path, Error* const error) { if (!g_dyn_sqlite.Open(error)) [[unlikely]] diff --git a/src/util/util.vcxproj b/src/util/util.vcxproj index dda5b39f3..ec74b7614 100644 --- a/src/util/util.vcxproj +++ b/src/util/util.vcxproj @@ -3,6 +3,8 @@ + + diff --git a/src/util/util.vcxproj.filters b/src/util/util.vcxproj.filters index 27f615e6f..8aec5cee3 100644 --- a/src/util/util.vcxproj.filters +++ b/src/util/util.vcxproj.filters @@ -87,6 +87,8 @@ + +