From b7541c35646efb02136d01ef97c42452265e6913 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 01/30] switch to SDL3 dep --- .ci/linux/build.sh | 4 +-- CMakeLists.txt | 34 +++++++++---------- CMakeModules/CopyYuzuSDLDeps.cmake | 2 +- CMakeModules/MinGWClangCross.cmake | 2 +- CMakeModules/MinGWCross.cmake | 2 +- cpmfile.json | 26 +++++++------- docs/Options.md | 4 +-- src/CMakeLists.txt | 2 +- src/android/app/build.gradle.kts | 2 +- src/audio_core/CMakeLists.txt | 6 ++-- src/audio_core/sink/sdl2_sink.cpp | 2 +- src/input_common/CMakeLists.txt | 6 ++-- src/input_common/drivers/sdl_driver.h | 2 +- src/yuzu/CMakeLists.txt | 6 ++-- src/yuzu/main.cpp | 2 +- src/yuzu_cmd/CMakeLists.txt | 2 +- src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 2 +- .../emu_window/emu_window_sdl2_gl.cpp | 2 +- .../emu_window/emu_window_sdl2_null.cpp | 2 +- .../emu_window/emu_window_sdl2_vk.cpp | 2 +- src/yuzu_cmd/sdl_config.cpp | 2 +- 21 files changed, 57 insertions(+), 57 deletions(-) diff --git a/.ci/linux/build.sh b/.ci/linux/build.sh index 41e0ca308b..f46dd9bdf1 100755 --- a/.ci/linux/build.sh +++ b/.ci/linux/build.sh @@ -97,8 +97,8 @@ cmake .. -G Ninja \ -DCMAKE_CXX_FLAGS="$ARCH_FLAGS" \ -DCMAKE_C_FLAGS="$ARCH_FLAGS" \ -DYUZU_USE_BUNDLED_QT=OFF \ - -DYUZU_USE_BUNDLED_SDL2=OFF \ - -DYUZU_USE_EXTERNAL_SDL2=ON \ + -DYUZU_USE_BUNDLED_SDL3=OFF \ + -DYUZU_USE_EXTERNAL_SDL3=ON \ -DYUZU_TESTS=OFF \ -DYUZU_USE_QT_MULTIMEDIA=$MULTIMEDIA \ -DYUZU_USE_QT_WEB_ENGINE=$WEBENGINE \ diff --git a/CMakeLists.txt b/CMakeLists.txt index a9ff2e9458..a690ebd119 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,14 +137,14 @@ if (PLATFORM_FREEBSD) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") endif() -# Set bundled sdl2/qt as dependent options. -# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion -cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) +# Set bundled sdl3/qt as dependent options. +# On Linux system SDL3 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion +cmake_dependent_option(ENABLE_SDL3 "Enable the SDL3 frontend" ON "NOT ANDROID" OFF) -if (ENABLE_SDL2) +if (ENABLE_SDL3) # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system - cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) - option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") + cmake_dependent_option(YUZU_USE_EXTERNAL_SDL3 "Compile external SDL3" OFF "NOT MSVC" OFF) + option(YUZU_USE_BUNDLED_SDL3 "Download bundled SDL3 build" "${MSVC}") endif() option(ENABLE_QT "Enable the Qt frontend" ON) @@ -215,7 +215,7 @@ option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) -cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) +cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL3;NOT ANDROID" OFF) cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) @@ -609,10 +609,10 @@ if(ENABLE_CUBEB) endif() endif() -# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package -if (ENABLE_SDL2) - if (YUZU_USE_EXTERNAL_SDL2) - message(STATUS "Using SDL2 from externals.") +# find SDL3 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package +if (ENABLE_SDL3) + if (YUZU_USE_EXTERNAL_SDL3) + message(STATUS "Using SDL3 from externals.") if (NOT WIN32) # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) @@ -635,16 +635,16 @@ if (ENABLE_SDL2) if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") set(SDL_PIPEWIRE OFF) # build errors out with this on - AddJsonPackage("sdl2_steamdeck") + AddJsonPackage("sdl3_steamdeck") else() - AddJsonPackage("sdl2_generic") + AddJsonPackage("sdl3_generic") endif() - elseif (YUZU_USE_BUNDLED_SDL2) - message(STATUS "Using bundled SDL2") - AddJsonPackage(sdl2) + elseif (YUZU_USE_BUNDLED_SDL3) + message(STATUS "Using bundled SDL3") + AddJsonPackage(sdl3) endif() - find_package(SDL2 2.26.4 REQUIRED) + find_package(SDL3 3.2.22 REQUIRED) endif() # List of all FFmpeg components required diff --git a/CMakeModules/CopyYuzuSDLDeps.cmake b/CMakeModules/CopyYuzuSDLDeps.cmake index 464eed5e9c..c3935794ca 100644 --- a/CMakeModules/CopyYuzuSDLDeps.cmake +++ b/CMakeModules/CopyYuzuSDLDeps.cmake @@ -4,5 +4,5 @@ function(copy_yuzu_SDL_deps target_dir) include(WindowsCopyFiles) set(DLL_DEST "$/") - windows_copy_files(${target_dir} ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll) + windows_copy_files(${target_dir} ${SDL3_DLL_DIR} ${DLL_DEST} SDL3.dll) endfunction(copy_yuzu_SDL_deps) diff --git a/CMakeModules/MinGWClangCross.cmake b/CMakeModules/MinGWClangCross.cmake index 286a59a7ad..11ed402380 100644 --- a/CMakeModules/MinGWClangCross.cmake +++ b/CMakeModules/MinGWClangCross.cmake @@ -6,7 +6,7 @@ set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) -set(SDL2_PATH ${MINGW_PREFIX}) +set(SDL3_PATH ${MINGW_PREFIX}) set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-) # Specify the cross compiler diff --git a/CMakeModules/MinGWCross.cmake b/CMakeModules/MinGWCross.cmake index 61464f7dae..5cebe81a6e 100644 --- a/CMakeModules/MinGWCross.cmake +++ b/CMakeModules/MinGWCross.cmake @@ -9,7 +9,7 @@ set(CMAKE_HOST_WIN32 TRUE) set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) -set(SDL2_PATH ${MINGW_PREFIX}) +set(SDL3_PATH ${MINGW_PREFIX}) set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-) # Specify the cross compiler diff --git a/cpmfile.json b/cpmfile.json index f1fd5ce1cf..8c596b67ba 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -157,30 +157,30 @@ "hash": "99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c", "find_args": "MODULE" }, - "sdl2_generic": { - "package": "SDL2", + "sdl3_generic": { + "package": "SDL3", "repo": "libsdl-org/SDL", - "sha": "54772f345a", - "hash": "2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4", + "sha": "a96677bdf6", + "hash": "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "key": "generic", "bundled": true }, - "sdl2_steamdeck": { - "package": "SDL2", + "sdl3_steamdeck": { + "package": "SDL3", "repo": "libsdl-org/SDL", "sha": "cc016b0046", "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", "key": "steamdeck", "bundled": true }, - "sdl2": { + "sdl3": { "ci": true, - "package": "SDL2", - "name": "SDL2", - "repo": "crueter-ci/SDL2", - "version": "2.32.8", - "min_version": "2.26.4", - "cmake_filename": "sdl2" + "package": "SDL3", + "name": "SDL3", + "repo": "libsdl-org/SDL3", + "version": "3.2.22", + "min_version": "3.2.0", + "cmake_filename": "sdl3" }, "llvm-mingw": { "repo": "misc/llvm-mingw", diff --git a/docs/Options.md b/docs/Options.md index 3dd84ea645..dc73fecd3e 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -40,12 +40,12 @@ Notes: * Unavailable on OpenBSD The following options are desktop only: -- `ENABLE_SDL2` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) +- `ENABLE_SDL3` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) * Unavailable on Android - `YUZU_USE_EXTERNAL_SDL2` (ON for non-UNIX) Compiles SDL2 from source - `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2 * Unavailable on OpenBSD - * Only enabled if YUZU_USE_CPM and ENABLE_SDL2 are both ON + * Only enabled if YUZU_USE_CPM and ENABLE_SDL3 are both ON - `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED) - `ENABLE_OPENGL` (ON) Enable the OpenGL graphics frontend * Unavailable on Windows/ARM64 and Android diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 88470c4c42..ed209890ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -223,7 +223,7 @@ if (YUZU_TESTS) add_subdirectory(tests) endif() -if (ENABLE_SDL2 AND YUZU_CMD) +if (ENABLE_SDL3 AND YUZU_CMD) add_subdirectory(yuzu_cmd) set_target_properties(yuzu-cmd PROPERTIES OUTPUT_NAME "eden-cli") endif() diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index e8d8141711..8dedf35446 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -168,7 +168,7 @@ android { cmake { arguments( "-DENABLE_QT=0", // Don't use QT - "-DENABLE_SDL2=0", // Don't use SDL + "-DENABLE_SDL3=0", // Don't use SDL "-DENABLE_WEB_SERVICE=1", // Enable web service "-DENABLE_OPENSSL=ON", "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index c9f8af7dc3..77ac05c7a2 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -247,14 +247,14 @@ if (ENABLE_CUBEB) target_compile_definitions(audio_core PRIVATE HAVE_CUBEB=1) endif() -if (ENABLE_SDL2) +if (ENABLE_SDL3) target_sources(audio_core PRIVATE sink/sdl2_sink.cpp sink/sdl2_sink.h ) - target_link_libraries(audio_core PRIVATE SDL2::SDL2) - target_compile_definitions(audio_core PRIVATE HAVE_SDL2) + target_link_libraries(audio_core PRIVATE SDL3::SDL3) + target_compile_definitions(audio_core PRIVATE HAVE_SDL3) endif() if(ANDROID) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 25ed58620e..4a9b537116 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "audio_core/common/common.h" #include "audio_core/sink/sdl2_sink.h" diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index d455323e05..05a123fd6e 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -47,7 +47,7 @@ else() ) endif() -if (ENABLE_SDL2) +if (ENABLE_SDL3) target_sources(input_common PRIVATE drivers/joycon.cpp drivers/joycon.h @@ -73,8 +73,8 @@ if (ENABLE_SDL2) helpers/joycon_protocol/rumble.cpp helpers/joycon_protocol/rumble.h ) - target_link_libraries(input_common PRIVATE SDL2::SDL2) - target_compile_definitions(input_common PRIVATE HAVE_SDL2) + target_link_libraries(input_common PRIVATE SDL3::SDL3) + target_compile_definitions(input_common PRIVATE HAVE_SDL3) endif() if (ENABLE_LIBUSB) diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index a140ad072c..58240d327c 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include "common/common_types.h" #include "common/threadsafe_queue.h" diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 00e03bd935..b47cce6137 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -468,9 +468,9 @@ if (YUZU_USE_BUNDLED_QT) copy_yuzu_Qt6_deps(yuzu) endif() -if (ENABLE_SDL2) - target_link_libraries(yuzu PRIVATE SDL2::SDL2) - target_compile_definitions(yuzu PRIVATE HAVE_SDL2) +if (ENABLE_SDL3) + target_link_libraries(yuzu PRIVATE SDL3::SDL3) + target_compile_definitions(yuzu PRIVATE HAVE_SDL3) endif() if (MSVC) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index fc7a953d77..58c1b151e2 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -98,7 +98,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #ifdef HAVE_SDL2 #include #include -#include // For SDL ScreenSaver functions +#include // For SDL ScreenSaver functions #endif #include diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index a60650bc19..47e0f7e5e1 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -41,7 +41,7 @@ target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) -target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2) +target_link_libraries(yuzu-cmd PRIVATE SDL3::SDL3) if(UNIX AND NOT APPLE) install(TARGETS yuzu-cmd) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 4b56f3794b..f0c1100d09 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -3,7 +3,7 @@ // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include +#include #include "common/logging/log.h" #include "common/scm_rev.h" diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 32f365e0d0..15b634bf63 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -9,7 +9,7 @@ #include #define SDL_MAIN_HANDLED -#include +#include #include #include diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index 506137bd8a..e4f01ece24 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -18,7 +18,7 @@ #include #endif -#include +#include EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index f509652bf6..ba4b29e9ae 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -12,7 +12,7 @@ #include "video_core/renderer_vulkan/renderer_vulkan.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" -#include +#include #include EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, diff --git a/src/yuzu_cmd/sdl_config.cpp b/src/yuzu_cmd/sdl_config.cpp index 6e0f254b6b..5d303571b1 100644 --- a/src/yuzu_cmd/sdl_config.cpp +++ b/src/yuzu_cmd/sdl_config.cpp @@ -3,7 +3,7 @@ // SDL will break our main function in yuzu-cmd if we don't define this before adding SDL.h #define SDL_MAIN_HANDLED -#include +#include #include "common/logging/log.h" #include "input_common/main.h" From 2634d04a49769c576d94a804f4b022e6b31936a1 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 02/30] rename all symbols --- src/audio_core/sink/sdl2_sink.cpp | 4 +- src/input_common/drivers/sdl_driver.cpp | 182 +++++++++--------- src/input_common/drivers/sdl_driver.h | 6 +- src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 42 ++-- .../emu_window/emu_window_sdl2_gl.cpp | 6 +- .../emu_window/emu_window_sdl2_null.cpp | 2 +- .../emu_window/emu_window_sdl2_vk.cpp | 4 +- 7 files changed, 123 insertions(+), 123 deletions(-) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 4a9b537116..72c02058b3 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp @@ -42,7 +42,7 @@ public: SDL_AudioSpec spec; spec.freq = TargetSampleRate; spec.channels = static_cast(device_channels); - spec.format = AUDIO_S16SYS; + spec.format = SDL_AUDIO_S16; spec.samples = TargetSampleCount * 2; spec.callback = &SDLSinkStream::DataCallback; spec.userdata = this; @@ -260,7 +260,7 @@ bool IsSDLSuitable() { SDL_AudioSpec spec; spec.freq = TargetSampleRate; spec.channels = 2u; - spec.format = AUDIO_S16SYS; + spec.format = SDL_AUDIO_S16; spec.samples = TargetSampleCount * 2; spec.callback = nullptr; spec.userdata = nullptr; diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 972abec9fe..100a2516e7 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -15,7 +15,7 @@ namespace InputCommon { namespace { Common::UUID GetGUID(SDL_Joystick* joystick) { - const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); + const SDL_GUID guid = SDL_GetJoystickGUID(joystick); std::array data{}; std::memcpy(data.data(), guid.data, sizeof(data)); // Clear controller name crc @@ -35,9 +35,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) { class SDLJoystick { public: SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, - SDL_GameController* game_controller) - : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, - sdl_controller{game_controller, &SDL_GameControllerClose} { + SDL_Gamepad* game_controller) + : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_CloseJoystick}, + sdl_controller{game_controller, &SDL_CloseGamepad} { EnableMotion(); } @@ -45,18 +45,18 @@ public: if (!sdl_controller) { return; } - SDL_GameController* controller = sdl_controller.get(); + SDL_Gamepad* controller = sdl_controller.get(); if (HasMotion()) { - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_FALSE); - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_FALSE); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, false); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, false); } - has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE; - has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE; + has_accel = SDL_GamepadHasSensor(controller, SDL_SENSOR_ACCEL) == true; + has_gyro = SDL_GamepadHasSensor(controller, SDL_SENSOR_GYRO) == true; if (has_accel) { - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, true); } if (has_gyro) { - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, true); } } @@ -64,7 +64,7 @@ public: return has_gyro || has_accel; } - bool UpdateMotion(SDL_ControllerSensorEvent event) { + bool UpdateMotion(SDL_GamepadSensorEvent event) { constexpr float gravity_constant = 9.80665f; std::scoped_lock lock{mutex}; const u64 time_difference = event.timestamp - last_motion_update; @@ -136,11 +136,11 @@ public: f32 high_amplitude = vibration.high_amplitude * high_frequency_scale; if (sdl_controller) { - return SDL_GameControllerRumble(sdl_controller.get(), static_cast(low_amplitude), + return SDL_RumbleGamepad(sdl_controller.get(), static_cast(low_amplitude), static_cast(high_amplitude), rumble_max_duration_ms) != -1; } else if (sdl_joystick) { - return SDL_JoystickRumble(sdl_joystick.get(), static_cast(low_amplitude), + return SDL_RumbleJoystick(sdl_joystick.get(), static_cast(low_amplitude), static_cast(high_amplitude), rumble_max_duration_ms) != -1; } @@ -150,11 +150,11 @@ public: bool HasHDRumble() const { if (sdl_controller) { - const auto type = SDL_GameControllerGetType(sdl_controller.get()); - return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) || - (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || - (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || - (type == SDL_CONTROLLER_TYPE_PS5); + const auto type = SDL_GetGamepadType(sdl_controller.get()); + return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) || + (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || + (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || + (type == SDL_GAMEPAD_TYPE_PS5); } return false; } @@ -201,11 +201,11 @@ public: return sdl_joystick.get(); } - SDL_GameController* GetSDLGameController() const { + SDL_Gamepad* GetSDLGameController() const { return sdl_controller.get(); } - void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) { + void SetSDLJoystick(SDL_Joystick* joystick, SDL_Gamepad* controller) { sdl_joystick.reset(joystick); sdl_controller.reset(controller); } @@ -253,28 +253,28 @@ public: std::string GetControllerName() const { if (sdl_controller) { - switch (SDL_GameControllerGetType(sdl_controller.get())) { - case SDL_CONTROLLER_TYPE_XBOX360: + switch (SDL_GetGamepadType(sdl_controller.get())) { + case SDL_GAMEPAD_TYPE_XBOX360: return "Xbox 360 Controller"; - case SDL_CONTROLLER_TYPE_XBOXONE: + case SDL_GAMEPAD_TYPE_XBOXONE: return "Xbox One Controller"; - case SDL_CONTROLLER_TYPE_PS3: + case SDL_GAMEPAD_TYPE_PS3: return "DualShock 3 Controller"; - case SDL_CONTROLLER_TYPE_PS4: + case SDL_GAMEPAD_TYPE_PS4: return "DualShock 4 Controller"; - case SDL_CONTROLLER_TYPE_PS5: + case SDL_GAMEPAD_TYPE_PS5: return "DualSense Controller"; default: break; } - const auto name = SDL_GameControllerName(sdl_controller.get()); + const auto name = SDL_GetGamepadName(sdl_controller.get()); if (name) { return name; } } if (sdl_joystick) { - const auto name = SDL_JoystickName(sdl_joystick.get()); + const auto name = SDL_GetJoystickName(sdl_joystick.get()); if (name) { return name; } @@ -286,8 +286,8 @@ public: private: Common::UUID guid; int port; - std::unique_ptr sdl_joystick; - std::unique_ptr sdl_controller; + std::unique_ptr sdl_joystick; + std::unique_ptr sdl_controller; mutable std::mutex mutex; u64 last_motion_update{}; @@ -323,7 +323,7 @@ std::shared_ptr SDLDriver::GetSDLJoystickByGUID(const std::string& } std::shared_ptr SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { - auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); + auto sdl_joystick = SDL_GetJoystickFromID(sdl_id); const auto guid = GetGUID(sdl_joystick); std::scoped_lock lock{joystick_map_mutex}; @@ -346,11 +346,11 @@ std::shared_ptr SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl } void SDLDriver::InitJoystick(int joystick_index) { - SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); - SDL_GameController* sdl_gamecontroller = nullptr; + SDL_Joystick* sdl_joystick = SDL_OpenJoystick(joystick_index); + SDL_Gamepad* sdl_gamecontroller = nullptr; - if (SDL_IsGameController(joystick_index)) { - sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); + if (SDL_IsGamepad(joystick_index)) { + sdl_gamecontroller = SDL_OpenGamepad(joystick_index); } if (!sdl_joystick) { @@ -364,7 +364,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) { LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); - SDL_JoystickClose(sdl_joystick); + SDL_CloseJoystick(sdl_joystick); return; } } @@ -372,7 +372,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (Settings::values.enable_procon_driver) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && guid.uuid[8] == 0x09) { LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); - SDL_JoystickClose(sdl_joystick); + SDL_CloseJoystick(sdl_joystick); return; } } @@ -428,35 +428,35 @@ void SDLDriver::PumpEvents() const { void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { switch (event.type) { - case SDL_JOYBUTTONUP: { + case SDL_EVENT_JOYSTICK_BUTTON_UP: { if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetButton(identifier, event.jbutton.button, false); } break; } - case SDL_JOYBUTTONDOWN: { + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: { if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetButton(identifier, event.jbutton.button, true); } break; } - case SDL_JOYHATMOTION: { + case SDL_EVENT_JOYSTICK_HAT_MOTION: { if (const auto joystick = GetSDLJoystickBySDLID(event.jhat.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetHatButton(identifier, event.jhat.hat, event.jhat.value); } break; } - case SDL_JOYAXISMOTION: { + case SDL_EVENT_JOYSTICK_AXIS_MOTION: { if (const auto joystick = GetSDLJoystickBySDLID(event.jaxis.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetAxis(identifier, event.jaxis.axis, event.jaxis.value / 32767.0f); } break; } - case SDL_CONTROLLERSENSORUPDATE: { + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: { if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { if (joystick->UpdateMotion(event.csensor)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); @@ -465,18 +465,18 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { } break; } - case SDL_JOYBATTERYUPDATED: { + case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: { if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level)); } break; } - case SDL_JOYDEVICEREMOVED: + case SDL_EVENT_JOYSTICK_REMOVED: LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); - CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); + CloseJoystick(SDL_GetJoystickFromID(event.jdevice.which)); break; - case SDL_JOYDEVICEADDED: + case SDL_EVENT_JOYSTICK_ADDED: LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which); InitJoystick(event.jdevice.which); break; @@ -502,8 +502,8 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); // Disable hidapi drivers for joycon controllers when the custom joycon driver is enabled @@ -533,8 +533,8 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); // If the frontend is going to manage the event loop, then we don't start one here - start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == 0; - if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { + start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) == 0; + if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { LOG_CRITICAL(Input, "SDL_Init failed with: {}", SDL_GetError()); return; } @@ -561,12 +561,12 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDLDriver::~SDLDriver() { CloseJoysticks(); - SDL_DelEventWatch(&SDLEventWatcher, this); + SDL_RemoveEventWatch(&SDLEventWatcher, this); initialized = false; if (start_thread) { vibration_thread.join(); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD); } } @@ -762,13 +762,13 @@ Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& g Common::ParamPackage SDLDriver::BuildParamPackageForBinding( int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const { switch (binding.bindType) { - case SDL_CONTROLLER_BINDTYPE_NONE: + case SDL_GAMEPAD_BINDTYPE_NONE: break; - case SDL_CONTROLLER_BINDTYPE_AXIS: + case SDL_GAMEPAD_BINDTYPE_AXIS: return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); - case SDL_CONTROLLER_BINDTYPE_BUTTON: + case SDL_GAMEPAD_BINDTYPE_BUTTON: return BuildButtonParamPackageForButton(port, guid, binding.value.button); - case SDL_CONTROLLER_BINDTYPE_HAT: + case SDL_GAMEPAD_BINDTYPE_HAT: return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat, static_cast(binding.value.hat.hat_mask)); } @@ -810,8 +810,8 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p // Add the missing bindings for ZL/ZR static constexpr ZButtonBindings switch_to_sdl_axis{{ - {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT}, - {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT}, + {Settings::NativeButton::ZL, SDL_GAMEPAD_AXIS_LEFT_TRIGGER}, + {Settings::NativeButton::ZR, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER}, }}; // Parameters contain two joysticks return dual @@ -830,41 +830,41 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p ButtonBindings SDLDriver::GetDefaultButtonBinding( const std::shared_ptr& joystick) const { // Default SL/SR mapping for other controllers - auto sll_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; - auto srl_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; - auto slr_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; - auto srr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; + auto sll_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; + auto srl_button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; + auto slr_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; + auto srr_button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; if (joystick->IsJoyconLeft()) { - sll_button = SDL_CONTROLLER_BUTTON_PADDLE2; - srl_button = SDL_CONTROLLER_BUTTON_PADDLE4; + sll_button = SDL_GAMEPAD_BUTTON_LEFT_PADDLE1; + srl_button = SDL_GAMEPAD_BUTTON_LEFT_PADDLE2; } if (joystick->IsJoyconRight()) { - slr_button = SDL_CONTROLLER_BUTTON_PADDLE3; - srr_button = SDL_CONTROLLER_BUTTON_PADDLE1; + slr_button = SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2; + srr_button = SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1; } return { - std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, - {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, - {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, - {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, - {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, - {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, - {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, - {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, - {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START}, - {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK}, - {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT}, - {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP}, - {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, - {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN}, + std::pair{Settings::NativeButton::A, SDL_GAMEPAD_BUTTON_EAST}, + {Settings::NativeButton::B, SDL_GAMEPAD_BUTTON_SOUTH}, + {Settings::NativeButton::X, SDL_GAMEPAD_BUTTON_NORTH}, + {Settings::NativeButton::Y, SDL_GAMEPAD_BUTTON_WEST}, + {Settings::NativeButton::LStick, SDL_GAMEPAD_BUTTON_LEFT_STICK}, + {Settings::NativeButton::RStick, SDL_GAMEPAD_BUTTON_RIGHT_STICK}, + {Settings::NativeButton::L, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {Settings::NativeButton::R, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, + {Settings::NativeButton::Plus, SDL_GAMEPAD_BUTTON_START}, + {Settings::NativeButton::Minus, SDL_GAMEPAD_BUTTON_BACK}, + {Settings::NativeButton::DLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT}, + {Settings::NativeButton::DUp, SDL_GAMEPAD_BUTTON_DPAD_UP}, + {Settings::NativeButton::DRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, + {Settings::NativeButton::DDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN}, {Settings::NativeButton::SLLeft, sll_button}, {Settings::NativeButton::SRLeft, srl_button}, {Settings::NativeButton::SLRight, slr_button}, {Settings::NativeButton::SRRight, srr_button}, - {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, - {Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1}, + {Settings::NativeButton::Home, SDL_GAMEPAD_BUTTON_GUIDE}, + {Settings::NativeButton::Screenshot, SDL_GAMEPAD_BUTTON_MISC1}, }; } @@ -960,9 +960,9 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p AnalogMapping mapping = {}; const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); if (params.Has("guid2")) { const auto identifier = joystick2->GetPadIdentifier(); PreSetController(identifier); @@ -987,9 +987,9 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p left_offset_x, left_offset_y)); } const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); const auto identifier = joystick->GetPadIdentifier(); PreSetController(identifier); PreSetAxis(identifier, binding_right_x.value.axis); @@ -1105,13 +1105,13 @@ bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) { const auto& axis_x = params.Get("axis_x", 0); const auto& axis_y = params.Get("axis_y", 0); const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) { return false; diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 58240d327c..bdd2476cb0 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -15,7 +15,7 @@ #include "input_common/input_engine.h" union SDL_Event; -using SDL_GameController = struct _SDL_GameController; +using SDL_Gamepad = struct _SDL_GameController; using SDL_Joystick = struct _SDL_Joystick; using SDL_JoystickID = s32; @@ -24,9 +24,9 @@ namespace InputCommon { class SDLJoystick; using ButtonBindings = - std::array, 20>; + std::array, 20>; using ZButtonBindings = - std::array, 2>; + std::array, 2>; class SDLDriver : public InputEngine { public: diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index f0c1100d09..cb3e4bc576 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -21,7 +21,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) : input_subsystem{input_subsystem_}, system{system_} { input_subsystem->Initialize(); - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}, Exiting...", SDL_GetError()); exit(1); } @@ -176,50 +176,50 @@ void EmuWindow_SDL2::WaitEvent() { switch (event.type) { case SDL_WINDOWEVENT: switch (event.window.event) { - case SDL_WINDOWEVENT_SIZE_CHANGED: - case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_MAXIMIZED: - case SDL_WINDOWEVENT_RESTORED: + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_MAXIMIZED: + case SDL_EVENT_WINDOW_RESTORED: OnResize(); break; - case SDL_WINDOWEVENT_MINIMIZED: - case SDL_WINDOWEVENT_EXPOSED: - is_shown = event.window.event == SDL_WINDOWEVENT_EXPOSED; + case SDL_EVENT_WINDOW_MINIMIZED: + case SDL_EVENT_WINDOW_EXPOSED: + is_shown = event.window.event == SDL_EVENT_WINDOW_EXPOSED; OnResize(); break; - case SDL_WINDOWEVENT_CLOSE: + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: is_open = false; break; } break; - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: OnKeyEvent(static_cast(event.key.keysym.scancode), event.key.state); break; - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: // ignore if it came from touch if (event.button.which != SDL_TOUCH_MOUSEID) OnMouseMotion(event.motion.x, event.motion.y); break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: // ignore if it came from touch if (event.button.which != SDL_TOUCH_MOUSEID) { OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); } break; - case SDL_FINGERDOWN: + case SDL_EVENT_FINGER_DOWN: OnFingerDown(event.tfinger.x, event.tfinger.y, static_cast(event.tfinger.touchId)); break; - case SDL_FINGERMOTION: + case SDL_EVENT_FINGER_MOTION: OnFingerMotion(event.tfinger.x, event.tfinger.y, static_cast(event.tfinger.touchId)); break; - case SDL_FINGERUP: + case SDL_EVENT_FINGER_UP: OnFingerUp(); break; - case SDL_QUIT: + case SDL_EVENT_QUIT: is_open = false; break; default: @@ -242,19 +242,19 @@ void EmuWindow_SDL2::WaitEvent() { // Credits to Samantas5855 and others for this function. void EmuWindow_SDL2::SetWindowIcon() { - SDL_RWops* const yuzu_icon_stream = SDL_RWFromConstMem((void*)yuzu_icon, yuzu_icon_size); + SDL_IOStream* const yuzu_icon_stream = SDL_IOFromConstMem((void*)yuzu_icon, yuzu_icon_size); if (yuzu_icon_stream == nullptr) { LOG_WARNING(Frontend, "Failed to create Eden icon stream."); return; } - SDL_Surface* const window_icon = SDL_LoadBMP_RW(yuzu_icon_stream, 1); + SDL_Surface* const window_icon = SDL_LoadBMP_IO(yuzu_icon_stream, 1); if (window_icon == nullptr) { LOG_WARNING(Frontend, "Failed to read BMP from stream."); return; } // The icon is attached to the window pointer SDL_SetWindowIcon(render_window, window_icon); - SDL_FreeSurface(window_icon); + SDL_DestroySurface(window_icon); } void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair minimal_size) { diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 15b634bf63..e08e843673 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -30,7 +30,7 @@ public: ~SDLGLContext() { DoneCurrent(); - SDL_GL_DeleteContext(context); + SDL_GL_DestroyContext(context); } void SwapBuffers() override { @@ -100,7 +100,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste SDL_WINDOWPOS_UNDEFINED, // x position SDL_WINDOWPOS_UNDEFINED, // y position Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); if (render_window == nullptr) { LOG_CRITICAL(Frontend, "Failed to create SDL2 window! {}", SDL_GetError()); @@ -148,7 +148,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste EmuWindow_SDL2_GL::~EmuWindow_SDL2_GL() { core_context.reset(); - SDL_GL_DeleteContext(window_context); + SDL_GL_DestroyContext(window_context); } std::unique_ptr EmuWindow_SDL2_GL::CreateSharedContext() const { diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index e4f01ece24..0eaecc6085 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -28,7 +28,7 @@ EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subs render_window = SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SetWindowIcon(); diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index ba4b29e9ae..dfac272342 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -25,11 +25,11 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste render_window = SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SDL_SysWMinfo wm; SDL_VERSION(&wm.version); - if (SDL_GetWindowWMInfo(render_window, &wm) == SDL_FALSE) { + if (SDL_GetWindowWMInfo(render_window, &wm) == false) { LOG_CRITICAL(Frontend, "Failed to get information from the window manager: {}", SDL_GetError()); std::exit(EXIT_FAILURE); From e41b50ada56677dd6b5e2c70ed7f64f06c0b306a Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 03/30] rename some headers --- src/input_common/drivers/joycon.h | 2 +- src/input_common/helpers/joycon_protocol/joycon_types.h | 2 +- src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp | 2 +- src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index 112e970e15..92ebf0c813 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "input_common/input_engine.h" diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index 792f124e14..439becb2ed 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include "common/bit_field.h" #include "common/common_funcs.h" diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index 0eaecc6085..cd1003a10e 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -15,7 +15,7 @@ #ifdef YUZU_USE_EXTERNAL_SDL2 // Include this before SDL.h to prevent the external from including a dummy #define USING_GENERATED_CONFIG_H -#include +#include #endif #include diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index dfac272342..3b3382556b 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -13,7 +13,7 @@ #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" #include -#include +#include EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) From 26ccc14d5a52b44ba4d9a12f540da50ba8e35f84 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 04/30] new audio api changes --- src/audio_core/sink/sdl2_sink.cpp | 190 +++++++++++++++--------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 72c02058b3..2d07a35c43 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp @@ -4,6 +4,7 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include @@ -13,7 +14,6 @@ #include "audio_core/sink/sdl2_sink.h" #include "audio_core/sink/sink_stream.h" #include "common/logging/log.h" -#include "common/scope_exit.h" #include "core/core.h" namespace AudioCore::Sink { @@ -39,37 +39,53 @@ public: system_channels = system_channels_; device_channels = device_channels_; - SDL_AudioSpec spec; + SDL_AudioSpec spec{}; spec.freq = TargetSampleRate; - spec.channels = static_cast(device_channels); + spec.channels = static_cast(device_channels); spec.format = SDL_AUDIO_S16; - spec.samples = TargetSampleCount * 2; - spec.callback = &SDLSinkStream::DataCallback; - spec.userdata = this; + SDL_AudioDeviceID device_id = 0; std::string device_name{output_device}; - bool capture{false}; + bool is_capture{false}; + if (type == StreamType::In) { device_name = input_device; - capture = true; + is_capture = true; } - SDL_AudioSpec obtained; - if (device_name.empty()) { - device = SDL_OpenAudioDevice(nullptr, capture, &spec, &obtained, false); - } else { - device = SDL_OpenAudioDevice(device_name.c_str(), capture, &spec, &obtained, false); + if (!device_name.empty()) { + int count = 0; + SDL_AudioDeviceID* devices = is_capture ? SDL_GetAudioRecordingDevices(&count) + : SDL_GetAudioPlaybackDevices(&count); + + if (devices) { + for (int i = 0; i < count; ++i) { + const char* name = SDL_GetAudioDeviceName(devices[i]); + if (name && device_name == name) { + device_id = devices[i]; + break; + } + } + SDL_free(devices); + } } - if (device == 0) { - LOG_CRITICAL(Audio_Sink, "Error opening SDL audio device: {}", SDL_GetError()); + if (device_id == 0) { + device_id = + is_capture ? SDL_AUDIO_DEVICE_DEFAULT_RECORDING : SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; + } + + stream = SDL_OpenAudioDeviceStream( + device_id, &spec, + is_capture ? &SDLSinkStream::CaptureCallback : &SDLSinkStream::PlaybackCallback, this); + + if (!stream) { + LOG_CRITICAL(Audio_Sink, "Error opening SDL audio stream: {}", SDL_GetError()); return; } - LOG_INFO(Service_Audio, - "Opening SDL stream {} with: rate {} channels {} (system channels {}) " - " samples {}", - device, obtained.freq, obtained.channels, system_channels, obtained.samples); + LOG_INFO(Service_Audio, "Opening SDL stream with: rate {} channels {} (system channels {})", + spec.freq, spec.channels, system_channels); } /** @@ -84,13 +100,14 @@ public: * Finalize the sink stream. */ void Finalize() override { - if (device == 0) { + if (!stream) { return; } Stop(); - SDL_ClearQueuedAudio(device); - SDL_CloseAudioDevice(device); + SDL_ClearAudioStream(stream); + SDL_DestroyAudioStream(stream); + stream = nullptr; } /** @@ -100,62 +117,80 @@ public: * Default false. */ void Start(bool resume = false) override { - if (device == 0 || !paused) { + if (!stream || !paused) { return; } paused = false; - SDL_PauseAudioDevice(device, 0); + SDL_ResumeAudioStreamDevice(stream); } /** * Stop the sink stream. */ void Stop() override { - if (device == 0 || paused) { + if (!stream || paused) { return; } SignalPause(); - SDL_PauseAudioDevice(device, 1); + SDL_PauseAudioStreamDevice(stream); + paused = true; } private: - /** - * Main callback from SDL. Either expects samples from us (audio render/audio out), or will - * provide samples to be copied (audio in). - * - * @param userdata - Custom data pointer passed along, points to a SDLSinkStream. - * @param stream - Buffer of samples to be filled or read. - * @param len - Length of the stream in bytes. - */ - static void DataCallback(void* userdata, Uint8* stream, int len) { + static void PlaybackCallback(void* userdata, SDL_AudioStream* stream, int additional_amount, + int total_amount) { auto* impl = static_cast(userdata); - if (!impl) { return; } const std::size_t num_channels = impl->GetDeviceChannels(); const std::size_t frame_size = num_channels; - const std::size_t num_frames{len / num_channels / sizeof(s16)}; + const std::size_t num_frames = additional_amount / (sizeof(s16) * frame_size); - if (impl->type == StreamType::In) { - std::span input_buffer{reinterpret_cast(stream), - num_frames * frame_size}; - impl->ProcessAudioIn(input_buffer, num_frames); - } else { - std::span output_buffer{reinterpret_cast(stream), num_frames * frame_size}; - impl->ProcessAudioOutAndRender(output_buffer, num_frames); + if (num_frames == 0) { + return; + } + + std::vector buffer(num_frames * frame_size); + impl->ProcessAudioOutAndRender(buffer, num_frames); + SDL_PutAudioStreamData(stream, buffer.data(), + static_cast(buffer.size() * sizeof(s16))); + } + + static void CaptureCallback(void* userdata, SDL_AudioStream* stream, int additional_amount, + int total_amount) { + auto* impl = static_cast(userdata); + if (!impl) { + return; + } + + const std::size_t num_channels = impl->GetDeviceChannels(); + const std::size_t frame_size = num_channels; + const std::size_t bytes_available = SDL_GetAudioStreamAvailable(stream); + + if (bytes_available == 0) { + return; + } + + const std::size_t num_frames = bytes_available / (sizeof(s16) * frame_size); + std::vector buffer(num_frames * frame_size); + + int bytes_read = + SDL_GetAudioStreamData(stream, buffer.data(), static_cast(bytes_available)); + if (bytes_read > 0) { + const std::size_t frames_read = bytes_read / (sizeof(s16) * frame_size); + impl->ProcessAudioIn(buffer, frames_read); } } - /// SDL device id of the opened input/output device - SDL_AudioDeviceID device{}; + SDL_AudioStream* stream{nullptr}; }; SDLSink::SDLSink(std::string_view target_device_name) { if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) { LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError()); return; } @@ -218,66 +253,31 @@ std::vector ListSDLSinkDevices(bool capture) { std::vector device_list; if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) { LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError()); return {}; } } - const int device_count = SDL_GetNumAudioDevices(capture); - for (int i = 0; i < device_count; ++i) { - if (const char* name = SDL_GetAudioDeviceName(i, capture)) { - device_list.emplace_back(name); + int count = 0; + SDL_AudioDeviceID* devices = + capture ? SDL_GetAudioRecordingDevices(&count) : SDL_GetAudioPlaybackDevices(&count); + + if (devices) { + for (int i = 0; i < count; ++i) { + const char* name = SDL_GetAudioDeviceName(devices[i]); + if (name) { + device_list.emplace_back(name); + } } + SDL_free(devices); } return device_list; } -/* REVERSION to 3833 - function GetSDLLatency() REINTRODUCED FROM 3833 - DIABLO 3 FIX */ u32 GetSDLLatency() { return TargetSampleCount * 2; } -// REVERTED back to 3833 - Below function IsSDLSuitable() removed, reverting to GetSDLLatency() above. - DIABLO 3 FIX -/* -bool IsSDLSuitable() { -#if !defined(HAVE_SDL2) - return false; -#else - // Check SDL can init - if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { - LOG_ERROR(Audio_Sink, "SDL failed to init, it is not suitable. Error: {}", - SDL_GetError()); - return false; - } - } - - // We can set any latency frequency we want with SDL, so no need to check that. - - // Check we can open a device with standard parameters - SDL_AudioSpec spec; - spec.freq = TargetSampleRate; - spec.channels = 2u; - spec.format = SDL_AUDIO_S16; - spec.samples = TargetSampleCount * 2; - spec.callback = nullptr; - spec.userdata = nullptr; - - SDL_AudioSpec obtained; - auto device = SDL_OpenAudioDevice(nullptr, false, &spec, &obtained, false); - - if (device == 0) { - LOG_ERROR(Audio_Sink, "SDL failed to open a device, it is not suitable. Error: {}", - SDL_GetError()); - return false; - } - - SDL_CloseAudioDevice(device); - return true; -#endif -} -*/ - -} // namespace AudioCore::Sink +} // namespace AudioCore::Sink \ No newline at end of file From a24d9ad40d4b1da36305439363fe68c1fc3e4ef7 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 05/30] gamepad and joystick apis --- src/input_common/drivers/sdl_driver.cpp | 349 ++++++++++++------------ src/input_common/drivers/sdl_driver.h | 50 +--- 2 files changed, 179 insertions(+), 220 deletions(-) diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 100a2516e7..d140b00ca0 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -8,7 +8,7 @@ #include "common/param_package.h" #include "common/settings.h" #include "common/thread.h" -#include "common/vector_math.h" +// #include "common/vector_math.h" // Not used directly #include "input_common/drivers/sdl_driver.h" namespace InputCommon { @@ -18,45 +18,41 @@ Common::UUID GetGUID(SDL_Joystick* joystick) { const SDL_GUID guid = SDL_GetJoystickGUID(joystick); std::array data{}; std::memcpy(data.data(), guid.data, sizeof(data)); - // Clear controller name crc std::memset(data.data() + 2, 0, sizeof(u16)); return Common::UUID{data}; } } // Anonymous namespace -static int SDLEventWatcher(void* user_data, SDL_Event* event) { +static bool SDLEventWatcher(void* user_data, SDL_Event* event) { auto* const sdl_state = static_cast(user_data); - sdl_state->HandleGameControllerEvent(*event); - - return 0; + return false; } class SDLJoystick { public: - SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, - SDL_Gamepad* game_controller) + SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, SDL_Gamepad* gamepad) : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_CloseJoystick}, - sdl_controller{game_controller, &SDL_CloseGamepad} { + sdl_gamepad{gamepad, &SDL_CloseGamepad} { EnableMotion(); } void EnableMotion() { - if (!sdl_controller) { + if (!sdl_gamepad) { return; } - SDL_Gamepad* controller = sdl_controller.get(); + SDL_Gamepad* gamepad = sdl_gamepad.get(); if (HasMotion()) { - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, false); - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, false); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_ACCEL, false); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, false); } - has_accel = SDL_GamepadHasSensor(controller, SDL_SENSOR_ACCEL) == true; - has_gyro = SDL_GamepadHasSensor(controller, SDL_SENSOR_GYRO) == true; + has_accel = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_ACCEL); + has_gyro = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_GYRO); if (has_accel) { - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, true); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_ACCEL, true); } if (has_gyro) { - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, true); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, true); } } @@ -84,25 +80,22 @@ public: } } - // Ignore duplicated timestamps if (time_difference == 0) { return false; } - // Motion data is invalid if (motion.accel_x == 0 && motion.gyro_x == 0 && motion.accel_y == 0 && motion.gyro_y == 0 && motion.accel_z == 0 && motion.gyro_z == 0) { if (motion_error_count++ < 200) { return false; } - // Try restarting the sensor motion_error_count = 0; EnableMotion(); return false; } motion_error_count = 0; - motion.delta_timestamp = time_difference * 1000; + motion.delta_timestamp = time_difference; return true; } @@ -116,13 +109,13 @@ public: constexpr f32 low_width_sensitivity_limit = 400.0f; constexpr f32 high_start_sensitivity_limit = 200.0f; constexpr f32 high_width_sensitivity_limit = 700.0f; - // Try to provide some feeling of the frequency by reducing the amplitude depending on it. + f32 low_frequency_scale = 1.0f; if (vibration.low_frequency > low_start_sensitivity_limit) { low_frequency_scale = (std::max)(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) / - low_width_sensitivity_limit, - 0.3f); + low_width_sensitivity_limit, + 0.3f); } f32 low_amplitude = vibration.low_amplitude * low_frequency_scale; @@ -130,27 +123,25 @@ public: if (vibration.high_frequency > high_start_sensitivity_limit) { high_frequency_scale = (std::max)(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) / - high_width_sensitivity_limit, - 0.3f); + high_width_sensitivity_limit, + 0.3f); } f32 high_amplitude = vibration.high_amplitude * high_frequency_scale; - if (sdl_controller) { - return SDL_RumbleGamepad(sdl_controller.get(), static_cast(low_amplitude), - static_cast(high_amplitude), - rumble_max_duration_ms) != -1; + if (sdl_gamepad) { + return SDL_RumbleGamepad(sdl_gamepad.get(), static_cast(low_amplitude), + static_cast(high_amplitude), rumble_max_duration_ms); } else if (sdl_joystick) { return SDL_RumbleJoystick(sdl_joystick.get(), static_cast(low_amplitude), - static_cast(high_amplitude), - rumble_max_duration_ms) != -1; + static_cast(high_amplitude), rumble_max_duration_ms); } return false; } bool HasHDRumble() const { - if (sdl_controller) { - const auto type = SDL_GetGamepadType(sdl_controller.get()); + if (sdl_gamepad) { + const auto type = SDL_GetGamepadType(sdl_gamepad.get()); return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) || (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || @@ -172,9 +163,6 @@ public: return is_vibration_tested; } - /** - * The Pad identifier of the joystick - */ const PadIdentifier GetPadIdentifier() const { return { .guid = guid, @@ -183,16 +171,10 @@ public: }; } - /** - * The guid of the joystick - */ const Common::UUID& GetGUID() const { return guid; } - /** - * The number of joystick from the same type that were connected before this joystick - */ int GetPort() const { return port; } @@ -201,13 +183,13 @@ public: return sdl_joystick.get(); } - SDL_Gamepad* GetSDLGameController() const { - return sdl_controller.get(); + SDL_Gamepad* GetSDLGamepad() const { + return sdl_gamepad.get(); } - void SetSDLJoystick(SDL_Joystick* joystick, SDL_Gamepad* controller) { + void SetSDLJoystick(SDL_Joystick* joystick, SDL_Gamepad* gamepad) { sdl_joystick.reset(joystick); - sdl_controller.reset(controller); + sdl_gamepad.reset(gamepad); } bool IsJoyconLeft() const { @@ -232,28 +214,27 @@ public: return false; } - Common::Input::BatteryLevel GetBatteryLevel(SDL_JoystickPowerLevel battery_level) { + Common::Input::BatteryLevel GetBatteryLevel(SDL_PowerState battery_level) { switch (battery_level) { - case SDL_JOYSTICK_POWER_EMPTY: - return Common::Input::BatteryLevel::Empty; - case SDL_JOYSTICK_POWER_LOW: + case SDL_POWERSTATE_ERROR: + case SDL_POWERSTATE_UNKNOWN: + return Common::Input::BatteryLevel::None; + case SDL_POWERSTATE_ON_BATTERY: return Common::Input::BatteryLevel::Low; - case SDL_JOYSTICK_POWER_MEDIUM: - return Common::Input::BatteryLevel::Medium; - case SDL_JOYSTICK_POWER_FULL: - case SDL_JOYSTICK_POWER_MAX: - return Common::Input::BatteryLevel::Full; - case SDL_JOYSTICK_POWER_WIRED: + case SDL_POWERSTATE_NO_BATTERY: + return Common::Input::BatteryLevel::None; + case SDL_POWERSTATE_CHARGING: return Common::Input::BatteryLevel::Charging; - case SDL_JOYSTICK_POWER_UNKNOWN: + case SDL_POWERSTATE_CHARGED: + return Common::Input::BatteryLevel::Full; default: return Common::Input::BatteryLevel::None; } } std::string GetControllerName() const { - if (sdl_controller) { - switch (SDL_GetGamepadType(sdl_controller.get())) { + if (sdl_gamepad) { + switch (SDL_GetGamepadType(sdl_gamepad.get())) { case SDL_GAMEPAD_TYPE_XBOX360: return "Xbox 360 Controller"; case SDL_GAMEPAD_TYPE_XBOXONE: @@ -267,7 +248,7 @@ public: default: break; } - const auto name = SDL_GetGamepadName(sdl_controller.get()); + const auto name = SDL_GetGamepadName(sdl_gamepad.get()); if (name) { return name; } @@ -287,7 +268,7 @@ private: Common::UUID guid; int port; std::unique_ptr sdl_joystick; - std::unique_ptr sdl_controller; + std::unique_ptr sdl_gamepad; mutable std::mutex mutex; u64 last_motion_update{}; @@ -345,16 +326,16 @@ std::shared_ptr SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl return *vec_it; } -void SDLDriver::InitJoystick(int joystick_index) { - SDL_Joystick* sdl_joystick = SDL_OpenJoystick(joystick_index); - SDL_Gamepad* sdl_gamecontroller = nullptr; +void SDLDriver::InitJoystick(SDL_JoystickID joystick_id) { + SDL_Joystick* sdl_joystick = SDL_OpenJoystick(joystick_id); + SDL_Gamepad* sdl_gamepad = nullptr; - if (SDL_IsGamepad(joystick_index)) { - sdl_gamecontroller = SDL_OpenGamepad(joystick_index); + if (SDL_IsGamepad(joystick_id)) { + sdl_gamepad = SDL_OpenGamepad(joystick_id); } if (!sdl_joystick) { - LOG_ERROR(Input, "Failed to open joystick {}", joystick_index); + LOG_ERROR(Input, "Failed to open joystick {}", joystick_id); return; } @@ -363,7 +344,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (Settings::values.enable_joycon_driver) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) { - LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); + LOG_WARNING(Input, "Preferring joycon driver for device ID {}", joystick_id); SDL_CloseJoystick(sdl_joystick); return; } @@ -371,7 +352,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (Settings::values.enable_procon_driver) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && guid.uuid[8] == 0x09) { - LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); + LOG_WARNING(Input, "Preferring joycon driver for device ID {}", joystick_id); SDL_CloseJoystick(sdl_joystick); return; } @@ -379,7 +360,7 @@ void SDLDriver::InitJoystick(int joystick_index) { std::scoped_lock lock{joystick_map_mutex}; if (joystick_map.find(guid) == joystick_map.end()) { - auto joystick = std::make_shared(guid, 0, sdl_joystick, sdl_gamecontroller); + auto joystick = std::make_shared(guid, 0, sdl_joystick, sdl_gamepad); PreSetController(joystick->GetPadIdentifier()); joystick->EnableMotion(); joystick_map[guid].emplace_back(std::move(joystick)); @@ -392,13 +373,13 @@ void SDLDriver::InitJoystick(int joystick_index) { [](const auto& joystick) { return !joystick->GetSDLJoystick(); }); if (joystick_it != joystick_guid_list.end()) { - (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); + (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamepad); (*joystick_it)->EnableMotion(); return; } const int port = static_cast(joystick_guid_list.size()); - auto joystick = std::make_shared(guid, port, sdl_joystick, sdl_gamecontroller); + auto joystick = std::make_shared(guid, port, sdl_joystick, sdl_gamepad); PreSetController(joystick->GetPadIdentifier()); joystick->EnableMotion(); joystick_guid_list.emplace_back(std::move(joystick)); @@ -408,7 +389,6 @@ void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { const auto guid = GetGUID(sdl_joystick); std::scoped_lock lock{joystick_map_mutex}; - // This call to guid is safe since the joystick is guaranteed to be in the map const auto& joystick_guid_list = joystick_map[guid]; const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), [&sdl_joystick](const auto& joystick) { @@ -457,8 +437,8 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { break; } case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: { - if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { - if (joystick->UpdateMotion(event.csensor)) { + if (auto joystick = GetSDLJoystickBySDLID(event.gsensor.which)) { + if (joystick->UpdateMotion(event.gsensor)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetMotion(identifier, 0, joystick->GetMotion()); } @@ -468,7 +448,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: { if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); - SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level)); + SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.state)); } break; } @@ -477,7 +457,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { CloseJoystick(SDL_GetJoystickFromID(event.jdevice.which)); break; case SDL_EVENT_JOYSTICK_ADDED: - LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which); + LOG_DEBUG(Input, "Controller connected with device ID {}", event.jdevice.which); InitJoystick(event.jdevice.which); break; } @@ -489,24 +469,17 @@ void SDLDriver::CloseJoysticks() { } SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) { - // Set our application name. Currently passed to DBus by SDL and visible to the user through - // their desktop environment. SDL_SetHint(SDL_HINT_APP_NAME, "Eden"); if (!Settings::values.enable_raw_input) { - // Disable raw input. When enabled this setting causes SDL to die when a web applet opens SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); } - // Prevent SDL from adding undesired axis - SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); - - // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers - SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); + // SDL_HINT_ACCELEROMETER_AS_JOYSTICK was removed in SDL3 + // SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE and SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE were removed in + // SDL3 These are now handled by SDL_HINT_JOYSTICK_ENHANCED_REPORTS SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - // Disable hidapi drivers for joycon controllers when the custom joycon driver is enabled if (Settings::values.enable_joycon_driver) { SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0"); } else { @@ -516,7 +489,6 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, "1"); } - // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled if (Settings::values.enable_procon_driver) { SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0"); } else { @@ -525,16 +497,11 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en } SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, "1"); - // Share the same button mapping with non-Nintendo controllers - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); - - // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native - // driver on Linux. + // SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS was removed in SDL3 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); - // If the frontend is going to manage the event loop, then we don't start one here - start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) == 0; - if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { + start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD); + if (start_thread && !SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD)) { LOG_CRITICAL(Input, "SDL_Init failed with: {}", SDL_GetError()); return; } @@ -552,10 +519,14 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en } }); } - // Because the events for joystick connection happens before we have our event watcher added, we - // can just open all the joysticks right here - for (int i = 0; i < SDL_NumJoysticks(); ++i) { - InitJoystick(i); + + int num_joysticks; + SDL_JoystickID* joysticks = SDL_GetJoysticks(&num_joysticks); + if (joysticks) { + for (int i = 0; i < num_joysticks; ++i) { + InitJoystick(joysticks[i]); + } + SDL_free(joysticks); } } @@ -592,7 +563,6 @@ std::vector SDLDriver::GetInputDevices() const { } } - // Add dual controllers for (const auto& [key, value] : joystick_map) { for (const auto& joystick : value) { if (joystick->IsJoyconRight()) { @@ -624,15 +594,12 @@ Common::Input::DriverResult SDLDriver::SetVibration( return (amplitude + std::pow(amplitude, factor)) * 0.5f * 0xFFFF; }; - // Default exponential curve for rumble f32 factor = 0.35f; - // If vibration is set as a linear output use a flatter value if (vibration.type == Common::Input::VibrationAmplificationType::Linear) { factor = 0.5f; } - // Amplitude for HD rumble needs no modification if (joystick->HasHDRumble()) { factor = 1.0f; } @@ -677,10 +644,7 @@ bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) { return joystick->HasVibration(); } - // First vibration might fail joystick->RumblePlay(test_vibration); - - // Wait for about 15ms to ensure the controller is ready for the stop command std::this_thread::sleep_for(std::chrono::milliseconds(15)); if (!joystick->RumblePlay(zero_vibration)) { @@ -760,17 +724,17 @@ Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& g } Common::ParamPackage SDLDriver::BuildParamPackageForBinding( - int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const { - switch (binding.bindType) { + int port, const Common::UUID& guid, const SDL_GamepadBinding& binding) const { + switch (binding.input_type) { case SDL_GAMEPAD_BINDTYPE_NONE: break; case SDL_GAMEPAD_BINDTYPE_AXIS: - return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); + return BuildAnalogParamPackageForButton(port, guid, binding.input.axis.axis); case SDL_GAMEPAD_BINDTYPE_BUTTON: - return BuildButtonParamPackageForButton(port, guid, binding.value.button); + return BuildButtonParamPackageForButton(port, guid, binding.input.button); case SDL_GAMEPAD_BINDTYPE_HAT: - return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat, - static_cast(binding.value.hat.hat_mask)); + return BuildHatParamPackageForButton(port, guid, binding.input.hat.hat, + static_cast(binding.input.hat.hat_mask)); } return {}; } @@ -797,28 +761,23 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p } const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return {}; } - // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. - // We will add those afterwards ButtonBindings switch_to_sdl_button; - switch_to_sdl_button = GetDefaultButtonBinding(joystick); - // Add the missing bindings for ZL/ZR static constexpr ZButtonBindings switch_to_sdl_axis{{ {Settings::NativeButton::ZL, SDL_GAMEPAD_AXIS_LEFT_TRIGGER}, {Settings::NativeButton::ZR, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER}, }}; - // Parameters contain two joysticks return dual if (params.Has("guid2")) { const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); - if (joystick2->GetSDLGameController() != nullptr) { + if (joystick2->GetSDLGamepad() != nullptr) { return GetDualControllerMapping(joystick, joystick2, switch_to_sdl_button, switch_to_sdl_axis); } @@ -829,7 +788,6 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p ButtonBindings SDLDriver::GetDefaultButtonBinding( const std::shared_ptr& joystick) const { - // Default SL/SR mapping for other controllers auto sll_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; auto srl_button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; auto slr_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; @@ -873,16 +831,25 @@ ButtonMapping SDLDriver::GetSingleControllerMapping( const ZButtonBindings& switch_to_sdl_axis) const { ButtonMapping mapping; mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); - auto* controller = joystick->GetSDLGameController(); for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { - const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); + // SDL_GetGamepadBindForButton was removed in SDL3 + // We need to use SDL_GetGamepadStringForButton or work with joystick directly + // For now, create a dummy binding + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; + binding.input.button = sdl_button; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); } for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { - const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); + // SDL_GetGamepadBindForAxis was removed in SDL3 + // We need to use SDL_GetGamepadStringForAxis or work with joystick directly + // For now, create a dummy binding + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding.input.axis.axis = sdl_axis; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); @@ -897,31 +864,41 @@ ButtonMapping SDLDriver::GetDualControllerMapping(const std::shared_ptrGetSDLGameController(); - auto* controller2 = joystick2->GetSDLGameController(); for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { if (IsButtonOnLeftSide(switch_button)) { - const auto& binding = SDL_GameControllerGetBindForButton(controller2, sdl_button); + // SDL_GetGamepadBindForButton was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; + binding.input.button = sdl_button; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding)); continue; } - const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); + // SDL_GetGamepadBindForButton was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; + binding.input.button = sdl_button; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); } for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { if (IsButtonOnLeftSide(switch_button)) { - const auto& binding = SDL_GameControllerGetBindForAxis(controller2, sdl_axis); + // SDL_GetGamepadBindForAxis was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding.input.axis.axis = sdl_axis; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding)); continue; } - const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); + // SDL_GetGamepadBindForAxis was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding.input.axis.axis = sdl_axis; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); @@ -953,53 +930,70 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p } const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return {}; } AnalogMapping mapping = {}; - const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); - const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); + // SDL_GetGamepadBindForAxis was removed in SDL3 + // We need to work with the underlying joystick directly + SDL_Joystick* sdl_joystick = SDL_GetGamepadJoystick(gamepad); + if (!sdl_joystick) { + return {}; + } + + // For now, use hardcoded axis mappings + SDL_GamepadBinding binding_left_x{}; + binding_left_x.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_left_x.input.axis.axis = 0; // Left stick X + + SDL_GamepadBinding binding_left_y{}; + binding_left_y.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_left_y.input.axis.axis = 1; // Left stick Y + if (params.Has("guid2")) { const auto identifier = joystick2->GetPadIdentifier(); PreSetController(identifier); - PreSetAxis(identifier, binding_left_x.value.axis); - PreSetAxis(identifier, binding_left_y.value.axis); - const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis); - const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis); + PreSetAxis(identifier, binding_left_x.input.axis.axis); + PreSetAxis(identifier, binding_left_y.input.axis.axis); + const auto left_offset_x = -GetAxis(identifier, binding_left_x.input.axis.axis); + const auto left_offset_y = GetAxis(identifier, binding_left_y.input.axis.axis); mapping.insert_or_assign(Settings::NativeAnalog::LStick, - BuildParamPackageForAnalog(identifier, binding_left_x.value.axis, - binding_left_y.value.axis, - left_offset_x, left_offset_y)); + BuildParamPackageForAnalog( + identifier, binding_left_x.input.axis.axis, + binding_left_y.input.axis.axis, left_offset_x, left_offset_y)); } else { const auto identifier = joystick->GetPadIdentifier(); PreSetController(identifier); - PreSetAxis(identifier, binding_left_x.value.axis); - PreSetAxis(identifier, binding_left_y.value.axis); - const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis); - const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis); + PreSetAxis(identifier, binding_left_x.input.axis.axis); + PreSetAxis(identifier, binding_left_y.input.axis.axis); + const auto left_offset_x = -GetAxis(identifier, binding_left_x.input.axis.axis); + const auto left_offset_y = GetAxis(identifier, binding_left_y.input.axis.axis); mapping.insert_or_assign(Settings::NativeAnalog::LStick, - BuildParamPackageForAnalog(identifier, binding_left_x.value.axis, - binding_left_y.value.axis, - left_offset_x, left_offset_y)); + BuildParamPackageForAnalog( + identifier, binding_left_x.input.axis.axis, + binding_left_y.input.axis.axis, left_offset_x, left_offset_y)); } - const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); - const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); + + // For right stick + SDL_GamepadBinding binding_right_x{}; + binding_right_x.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_right_x.input.axis.axis = 2; // Right stick X + + SDL_GamepadBinding binding_right_y{}; + binding_right_y.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_right_y.input.axis.axis = 3; // Right stick Y const auto identifier = joystick->GetPadIdentifier(); PreSetController(identifier); - PreSetAxis(identifier, binding_right_x.value.axis); - PreSetAxis(identifier, binding_right_y.value.axis); - const auto right_offset_x = -GetAxis(identifier, binding_right_x.value.axis); - const auto right_offset_y = GetAxis(identifier, binding_right_y.value.axis); + PreSetAxis(identifier, binding_right_x.input.axis.axis); + PreSetAxis(identifier, binding_right_y.input.axis.axis); + const auto right_offset_x = -GetAxis(identifier, binding_right_x.input.axis.axis); + const auto right_offset_y = GetAxis(identifier, binding_right_y.input.axis.axis); mapping.insert_or_assign(Settings::NativeAnalog::RStick, - BuildParamPackageForAnalog(identifier, binding_right_x.value.axis, - binding_right_y.value.axis, right_offset_x, - right_offset_y)); + BuildParamPackageForAnalog(identifier, binding_right_x.input.axis.axis, + binding_right_y.input.axis.axis, + right_offset_x, right_offset_y)); return mapping; } @@ -1009,8 +1003,8 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p } const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return {}; } @@ -1039,7 +1033,6 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p Common::Input::ButtonNames SDLDriver::GetUIName(const Common::ParamPackage& params) const { if (params.Has("button")) { - // TODO(German77): Find how to substitute the values for real button names return Common::Input::ButtonNames::Value; } if (params.Has("hat")) { @@ -1097,29 +1090,27 @@ bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) { if (joystick == nullptr) { return false; } - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return false; } const auto& axis_x = params.Get("axis_x", 0); const auto& axis_y = params.Get("axis_y", 0); - const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); - const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); - const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); - const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); + // SDL_GetGamepadBindForAxis was removed in SDL3 + // Use hardcoded axis mappings for now + const int binding_left_x = 0; // Left stick X + const int binding_right_x = 2; // Right stick X + const int binding_left_y = 1; // Left stick Y + const int binding_right_y = 3; // Right stick Y - if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) { + if (axis_x != binding_left_y && axis_x != binding_right_y) { return false; } - if (axis_y != binding_left_x.value.axis && axis_y != binding_right_x.value.axis) { + if (axis_y != binding_left_x && axis_y != binding_right_x) { return false; } return true; } -} // namespace InputCommon +} // namespace InputCommon \ No newline at end of file diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index bdd2476cb0..98f29e488a 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -15,39 +15,26 @@ #include "input_common/input_engine.h" union SDL_Event; -using SDL_Gamepad = struct _SDL_GameController; -using SDL_Joystick = struct _SDL_Joystick; -using SDL_JoystickID = s32; +using SDL_Gamepad = struct SDL_Gamepad; +using SDL_Joystick = struct SDL_Joystick; +using SDL_JoystickID = Uint32; namespace InputCommon { class SDLJoystick; -using ButtonBindings = - std::array, 20>; -using ZButtonBindings = - std::array, 2>; +using ButtonBindings = std::array, 20>; +using ZButtonBindings = std::array, 2>; class SDLDriver : public InputEngine { public: - /// Initializes and registers SDL device factories explicit SDLDriver(std::string input_engine_); - - /// Unregisters SDL device factories and shut them down. ~SDLDriver() override; void PumpEvents() const; - - /// Handle SDL_Events for joysticks from SDL_PollEvent void HandleGameControllerEvent(const SDL_Event& event); - /// Get the nth joystick with the corresponding GUID std::shared_ptr GetSDLJoystickBySDLID(SDL_JoystickID sdl_id); - - /** - * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so - * tie it to a SDLJoystick with the same guid and that port - */ std::shared_ptr GetSDLJoystickByGUID(const Common::UUID& guid, int port); std::shared_ptr GetSDLJoystickByGUID(const std::string& guid, int port); @@ -69,59 +56,40 @@ public: bool IsVibrationEnabled(const PadIdentifier& identifier) override; private: - void InitJoystick(int joystick_index); + void InitJoystick(SDL_JoystickID joystick_id); void CloseJoystick(SDL_Joystick* sdl_joystick); - - /// Needs to be called before SDL_QuitSubSystem. void CloseJoysticks(); - - /// Takes all vibrations from the queue and sends the command to the controller void SendVibrations(); Common::ParamPackage BuildAnalogParamPackageForButton(int port, const Common::UUID& guid, s32 axis, float value = 0.1f) const; Common::ParamPackage BuildButtonParamPackageForButton(int port, const Common::UUID& guid, s32 button) const; - Common::ParamPackage BuildHatParamPackageForButton(int port, const Common::UUID& guid, s32 hat, u8 value) const; - Common::ParamPackage BuildMotionParam(int port, const Common::UUID& guid) const; - - Common::ParamPackage BuildParamPackageForBinding( - int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const; - + Common::ParamPackage BuildParamPackageForBinding(int port, const Common::UUID& guid, + const SDL_GamepadBinding& binding) const; Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, int axis_y, float offset_x, float offset_y) const; - /// Returns the default button bindings list ButtonBindings GetDefaultButtonBinding(const std::shared_ptr& joystick) const; - - /// Returns the button mappings from a single controller ButtonMapping GetSingleControllerMapping(const std::shared_ptr& joystick, const ButtonBindings& switch_to_sdl_button, const ZButtonBindings& switch_to_sdl_axis) const; - - /// Returns the button mappings from two different controllers ButtonMapping GetDualControllerMapping(const std::shared_ptr& joystick, const std::shared_ptr& joystick2, const ButtonBindings& switch_to_sdl_button, const ZButtonBindings& switch_to_sdl_axis) const; - - /// Returns true if the button is on the left joycon bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; - /// Queue of vibration request to controllers Common::SPSCQueue vibration_queue; - - /// Map of GUID of a list of corresponding virtual Joysticks std::unordered_map>> joystick_map; std::mutex joystick_map_mutex; bool start_thread = false; std::atomic initialized = false; - std::thread vibration_thread; }; -} // namespace InputCommon +} // namespace InputCommon \ No newline at end of file From 66e11f28d74f068ff42cf5225598dd3548768508 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 06/30] windowing and input stuff --- src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 115 +++++++++--------- src/yuzu_cmd/emu_window/emu_window_sdl2.h | 12 +- .../emu_window/emu_window_sdl2_gl.cpp | 31 +++-- src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h | 9 +- .../emu_window/emu_window_sdl2_null.cpp | 17 ++- .../emu_window/emu_window_sdl2_null.h | 6 +- .../emu_window/emu_window_sdl2_vk.cpp | 95 +++++++-------- src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h | 6 +- src/yuzu_cmd/yuzu.cpp | 8 +- 9 files changed, 139 insertions(+), 160 deletions(-) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index cb3e4bc576..38754fe7f0 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -4,7 +4,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include - +#include +#include #include "common/logging/log.h" #include "common/scm_rev.h" #include "common/settings.h" @@ -18,23 +19,23 @@ #include "yuzu_cmd/emu_window/emu_window_sdl2.h" #include "yuzu_cmd/yuzu_icon.h" -EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) +EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) : input_subsystem{input_subsystem_}, system{system_} { input_subsystem->Initialize(); - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { - LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}, Exiting...", SDL_GetError()); + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD)) { + LOG_CRITICAL(Frontend, "Failed to initialize SDL3: {}, Exiting...", SDL_GetError()); exit(1); } SDL_SetMainReady(); } -EmuWindow_SDL2::~EmuWindow_SDL2() { +EmuWindow_SDL3::~EmuWindow_SDL3() { system.HIDCore().UnloadInputDevices(); input_subsystem->Shutdown(); SDL_Quit(); } -InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const { +InputCommon::MouseButton EmuWindow_SDL3::SDLButtonToMouseButton(u32 button) const { switch (button) { case SDL_BUTTON_LEFT: return InputCommon::MouseButton::Left; @@ -52,21 +53,17 @@ InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) cons } /// @brief Translates pixel position to float position -EmuWindow_SDL2::FloatPairNonHFA EmuWindow_SDL2::MouseToTouchPos(s32 touch_x, s32 touch_y) const { +EmuWindow_SDL3::FloatPairNonHFA EmuWindow_SDL3::MouseToTouchPos(s32 touch_x, s32 touch_y) const { int w = 0, h = 0; SDL_GetWindowSize(render_window, &w, &h); const float fx = float(touch_x) / w; const float fy = float(touch_y) / h; - return { - std::clamp(fx, 0.0f, 1.0f), - std::clamp(fy, 0.0f, 1.0f), - 0 - }; + return {std::clamp(fx, 0.0f, 1.0f), std::clamp(fy, 0.0f, 1.0f), 0}; } -void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { +void EmuWindow_SDL3::OnMouseButton(u32 button, bool pressed, s32 x, s32 y) { const auto mouse_button = SDLButtonToMouseButton(button); - if (state == SDL_PRESSED) { + if (pressed) { auto const [touch_x, touch_y, _] = MouseToTouchPos(x, y); input_subsystem->GetMouse()->PressButton(x, y, mouse_button); input_subsystem->GetMouse()->PressMouseButton(mouse_button); @@ -76,64 +73,65 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { } } -void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { +void EmuWindow_SDL3::OnMouseMotion(s32 x, s32 y) { auto const [touch_x, touch_y, _] = MouseToTouchPos(x, y); input_subsystem->GetMouse()->Move(x, y, 0, 0); input_subsystem->GetMouse()->MouseMove(touch_x, touch_y); input_subsystem->GetMouse()->TouchMove(touch_x, touch_y); } -void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) { +void EmuWindow_SDL3::OnFingerDown(float x, float y, std::size_t id) { input_subsystem->GetTouchScreen()->TouchPressed(x, y, id); } -void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) { +void EmuWindow_SDL3::OnFingerMotion(float x, float y, std::size_t id) { input_subsystem->GetTouchScreen()->TouchMoved(x, y, id); } -void EmuWindow_SDL2::OnFingerUp() { +void EmuWindow_SDL3::OnFingerUp() { input_subsystem->GetTouchScreen()->ReleaseAllTouch(); } -void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { - if (state == SDL_PRESSED) { +void EmuWindow_SDL3::OnKeyEvent(int key, bool pressed) { + if (pressed) { input_subsystem->GetKeyboard()->PressKey(static_cast(key)); - } else if (state == SDL_RELEASED) { + } else { input_subsystem->GetKeyboard()->ReleaseKey(static_cast(key)); } } -bool EmuWindow_SDL2::IsOpen() const { +bool EmuWindow_SDL3::IsOpen() const { return is_open; } -bool EmuWindow_SDL2::IsShown() const { +bool EmuWindow_SDL3::IsShown() const { return is_shown; } -void EmuWindow_SDL2::OnResize() { +void EmuWindow_SDL3::OnResize() { int width, height; - SDL_GL_GetDrawableSize(render_window, &width, &height); + SDL_GetWindowSizeInPixels(render_window, &width, &height); UpdateCurrentFramebufferLayout(width, height); } -void EmuWindow_SDL2::ShowCursor(bool show_cursor) { - SDL_ShowCursor(show_cursor ? SDL_ENABLE : SDL_DISABLE); +void EmuWindow_SDL3::ShowCursor(bool show_cursor) { + show_cursor ? SDL_ShowCursor() : SDL_HideCursor(); } -void EmuWindow_SDL2::Fullscreen() { - SDL_DisplayMode display_mode; +void EmuWindow_SDL3::Fullscreen() { + const SDL_DisplayMode* display_mode; switch (Settings::values.fullscreen_mode.GetValue()) { case Settings::FullscreenMode::Exclusive: - // Set window size to render size before entering fullscreen -- SDL2 does not resize window + // Set window size to render size before entering fullscreen -- SDL3 does not resize window // to display dimensions automatically in this mode. - if (SDL_GetDesktopDisplayMode(0, &display_mode) == 0) { - SDL_SetWindowSize(render_window, display_mode.w, display_mode.h); + display_mode = SDL_GetDesktopDisplayMode(0); + if (display_mode) { + SDL_SetWindowSize(render_window, display_mode->w, display_mode->h); } else { LOG_ERROR(Frontend, "SDL_GetDesktopDisplayMode failed: {}", SDL_GetError()); } - if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) { + if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN)) { return; } @@ -141,7 +139,7 @@ void EmuWindow_SDL2::Fullscreen() { LOG_INFO(Frontend, "Attempting to use borderless fullscreen..."); [[fallthrough]]; case Settings::FullscreenMode::Borderless: - if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) { + if (SDL_SetWindowFullscreen(render_window, true)) { return; } @@ -156,11 +154,13 @@ void EmuWindow_SDL2::Fullscreen() { } } -void EmuWindow_SDL2::WaitEvent() { +void EmuWindow_SDL3::WaitEvent() { // Called on main thread SDL_Event event; - if (!SDL_WaitEvent(&event)) { + if (SDL_WaitEvent(&event)) { + // Event received successfully + } else { const char* error = SDL_GetError(); if (!error || strcmp(error, "") == 0) { // https://github.com/libsdl-org/SDL/issues/5780 @@ -174,27 +174,23 @@ void EmuWindow_SDL2::WaitEvent() { } switch (event.type) { - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: - case SDL_EVENT_WINDOW_RESIZED: - case SDL_EVENT_WINDOW_MAXIMIZED: - case SDL_EVENT_WINDOW_RESTORED: - OnResize(); - break; - case SDL_EVENT_WINDOW_MINIMIZED: - case SDL_EVENT_WINDOW_EXPOSED: - is_shown = event.window.event == SDL_EVENT_WINDOW_EXPOSED; - OnResize(); - break; - case SDL_EVENT_WINDOW_CLOSE_REQUESTED: - is_open = false; - break; - } + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_MAXIMIZED: + case SDL_EVENT_WINDOW_RESTORED: + OnResize(); + break; + case SDL_EVENT_WINDOW_MINIMIZED: + case SDL_EVENT_WINDOW_EXPOSED: + is_shown = event.type == SDL_EVENT_WINDOW_EXPOSED; + OnResize(); + break; + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + is_open = false; break; case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: - OnKeyEvent(static_cast(event.key.keysym.scancode), event.key.state); + OnKeyEvent(static_cast(event.key.scancode), event.type == SDL_EVENT_KEY_DOWN); break; case SDL_EVENT_MOUSE_MOTION: // ignore if it came from touch @@ -205,16 +201,17 @@ void EmuWindow_SDL2::WaitEvent() { case SDL_EVENT_MOUSE_BUTTON_UP: // ignore if it came from touch if (event.button.which != SDL_TOUCH_MOUSEID) { - OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); + OnMouseButton(event.button.button, event.type == SDL_EVENT_MOUSE_BUTTON_DOWN, + event.button.x, event.button.y); } break; case SDL_EVENT_FINGER_DOWN: OnFingerDown(event.tfinger.x, event.tfinger.y, - static_cast(event.tfinger.touchId)); + static_cast(event.tfinger.touchID)); break; case SDL_EVENT_FINGER_MOTION: OnFingerMotion(event.tfinger.x, event.tfinger.y, - static_cast(event.tfinger.touchId)); + static_cast(event.tfinger.touchID)); break; case SDL_EVENT_FINGER_UP: OnFingerUp(); @@ -241,7 +238,7 @@ void EmuWindow_SDL2::WaitEvent() { } // Credits to Samantas5855 and others for this function. -void EmuWindow_SDL2::SetWindowIcon() { +void EmuWindow_SDL3::SetWindowIcon() { SDL_IOStream* const yuzu_icon_stream = SDL_IOFromConstMem((void*)yuzu_icon, yuzu_icon_size); if (yuzu_icon_stream == nullptr) { LOG_WARNING(Frontend, "Failed to create Eden icon stream."); @@ -257,6 +254,6 @@ void EmuWindow_SDL2::SetWindowIcon() { SDL_DestroySurface(window_icon); } -void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair minimal_size) { +void EmuWindow_SDL3::OnMinimalClientAreaChangeRequest(std::pair minimal_size) { SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 8aec1efda0..1e330afc59 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h @@ -22,10 +22,10 @@ class InputSubsystem; enum class MouseButton; } // namespace InputCommon -class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { +class EmuWindow_SDL3 : public Core::Frontend::EmuWindow { public: - explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_); - ~EmuWindow_SDL2(); + explicit EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_); + ~EmuWindow_SDL3(); /// Whether the window is still open, and a close request hasn't yet been sent bool IsOpen() const; @@ -41,7 +41,7 @@ public: protected: /// Called by WaitEvent when a key is pressed or released. - void OnKeyEvent(int key, u8 state); + void OnKeyEvent(int key, bool pressed); /// Converts a SDL mouse button into MouseInput mouse button InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const; @@ -53,7 +53,7 @@ protected: FloatPairNonHFA MouseToTouchPos(s32 touch_x, s32 touch_y) const; /// Called by WaitEvent when a mouse button is pressed or released - void OnMouseButton(u32 button, u8 state, s32 x, s32 y); + void OnMouseButton(u32 button, bool pressed, s32 x, s32 y); /// Called by WaitEvent when the mouse moves. void OnMouseMotion(s32 x, s32 y); @@ -85,7 +85,7 @@ protected: /// Is the window being shown? bool is_shown = true; - /// Internal SDL2 render window + /// Internal SDL3 render window SDL_Window* render_window{}; /// Keeps track of how often to update the title bar during gameplay diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index e08e843673..4e00fa91a8 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -4,7 +4,6 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include #include @@ -16,7 +15,6 @@ #include "common/logging/log.h" #include "common/scm_rev.h" #include "common/settings.h" -#include "common/string_util.h" #include "core/core.h" #include "input_common/main.h" #include "video_core/renderer_base.h" @@ -58,7 +56,7 @@ private: bool is_current = false; }; -bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { +bool EmuWindow_SDL3_GL::SupportsRequiredGLExtensions() { std::vector unsupported_ext; // Extensions required to support some texture formats. @@ -76,9 +74,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { return unsupported_ext.empty(); } -EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_, +EmuWindow_SDL3_GL::EmuWindow_SDL3_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) - : EmuWindow_SDL2{input_subsystem_, system_} { + : EmuWindow_SDL3{input_subsystem_, system_} { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); @@ -95,15 +93,12 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste std::string window_title = fmt::format("{} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); - render_window = - SDL_CreateWindow(window_title.c_str(), - SDL_WINDOWPOS_UNDEFINED, // x position - SDL_WINDOWPOS_UNDEFINED, // y position - Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); + render_window = SDL_CreateWindow( + window_title.c_str(), Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); if (render_window == nullptr) { - LOG_CRITICAL(Frontend, "Failed to create SDL2 window! {}", SDL_GetError()); + LOG_CRITICAL(Frontend, "Failed to create SDL3 window! {}", SDL_GetError()); exit(1); } @@ -120,15 +115,17 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste core_context = CreateSharedContext(); if (window_context == nullptr) { - LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context: {}", SDL_GetError()); + LOG_CRITICAL(Frontend, "Failed to create SDL3 GL context: {}", SDL_GetError()); exit(1); } if (core_context == nullptr) { - LOG_CRITICAL(Frontend, "Failed to create shared SDL2 GL context: {}", SDL_GetError()); + LOG_CRITICAL(Frontend, "Failed to create shared SDL3 GL context: {}", SDL_GetError()); exit(1); } - if (!gladLoadGLLoader(static_cast(SDL_GL_GetProcAddress))) { + if (!gladLoadGLLoader([](const char* name) -> void* { + return reinterpret_cast(SDL_GL_GetProcAddress(name)); + })) { LOG_CRITICAL(Frontend, "Failed to initialize GL functions! {}", SDL_GetError()); exit(1); } @@ -146,11 +143,11 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste Settings::LogSettings(); } -EmuWindow_SDL2_GL::~EmuWindow_SDL2_GL() { +EmuWindow_SDL3_GL::~EmuWindow_SDL3_GL() { core_context.reset(); SDL_GL_DestroyContext(window_context); } -std::unique_ptr EmuWindow_SDL2_GL::CreateSharedContext() const { +std::unique_ptr EmuWindow_SDL3_GL::CreateSharedContext() const { return std::make_unique(render_window); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h index 39346e7047..345ee17760 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "core/frontend/emu_window.h" #include "yuzu_cmd/emu_window/emu_window_sdl2.h" @@ -15,11 +16,11 @@ namespace InputCommon { class InputSubsystem; } -class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { +class EmuWindow_SDL3_GL final : public EmuWindow_SDL3 { public: - explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, + explicit EmuWindow_SDL3_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen); - ~EmuWindow_SDL2_GL(); + ~EmuWindow_SDL3_GL(); std::unique_ptr CreateSharedContext() const override; @@ -27,8 +28,6 @@ private: /// Whether the GPU and driver supports the OpenGL extension required bool SupportsRequiredGLExtensions(); - using SDL_GLContext = void*; - /// The OpenGL context associated with the window SDL_GLContext window_context; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index cd1003a10e..36f61bd6f1 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -12,7 +12,7 @@ #include "video_core/renderer_null/renderer_null.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" -#ifdef YUZU_USE_EXTERNAL_SDL2 +#ifdef YUZU_USE_EXTERNAL_SDL3 // Include this before SDL.h to prevent the external from including a dummy #define USING_GENERATED_CONFIG_H #include @@ -20,15 +20,14 @@ #include -EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, +EmuWindow_SDL3_Null::EmuWindow_SDL3_Null(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) - : EmuWindow_SDL2{input_subsystem_, system_} { + : EmuWindow_SDL3{input_subsystem_, system_} { const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc); - render_window = - SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); + render_window = SDL_CreateWindow(window_title.c_str(), Layout::ScreenUndocked::Width, + Layout::ScreenUndocked::Height, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SetWindowIcon(); @@ -44,8 +43,8 @@ EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subs Common::g_scm_branch, Common::g_scm_desc); } -EmuWindow_SDL2_Null::~EmuWindow_SDL2_Null() = default; +EmuWindow_SDL3_Null::~EmuWindow_SDL3_Null() = default; -std::unique_ptr EmuWindow_SDL2_Null::CreateSharedContext() const { +std::unique_ptr EmuWindow_SDL3_Null::CreateSharedContext() const { return std::make_unique(); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h index 35aee286df..f194d137ae 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h @@ -16,11 +16,11 @@ namespace InputCommon { class InputSubsystem; } -class EmuWindow_SDL2_Null final : public EmuWindow_SDL2 { +class EmuWindow_SDL3_Null final : public EmuWindow_SDL3 { public: - explicit EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, + explicit EmuWindow_SDL3_Null(InputCommon::InputSubsystem* input_subsystem_, Core::System& system, bool fullscreen); - ~EmuWindow_SDL2_Null() override; + ~EmuWindow_SDL3_Null() override; std::unique_ptr CreateSharedContext() const override; }; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index 3b3382556b..ee43f130ce 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -9,31 +9,18 @@ #include "common/logging/log.h" #include "common/scm_rev.h" -#include "video_core/renderer_vulkan/renderer_vulkan.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" #include -#include -EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, +EmuWindow_SDL3_VK::EmuWindow_SDL3_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) - : EmuWindow_SDL2{input_subsystem_, system_} { - const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", - Common::g_build_name, - Common::g_scm_branch, - Common::g_scm_desc); - render_window = - SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); - - SDL_SysWMinfo wm; - SDL_VERSION(&wm.version); - if (SDL_GetWindowWMInfo(render_window, &wm) == false) { - LOG_CRITICAL(Frontend, "Failed to get information from the window manager: {}", - SDL_GetError()); - std::exit(EXIT_FAILURE); - } + : EmuWindow_SDL3{input_subsystem_, system_} { + const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", Common::g_build_name, + Common::g_scm_branch, Common::g_scm_desc); + render_window = SDL_CreateWindow(window_title.c_str(), Layout::ScreenUndocked::Width, + Layout::ScreenUndocked::Height, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SetWindowIcon(); @@ -42,43 +29,43 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste ShowCursor(false); } - switch (wm.subsystem) { -#ifdef SDL_VIDEO_DRIVER_WINDOWS - case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS: + { + SDL_PropertiesID props = SDL_GetWindowProperties(render_window); + +#if defined(SDL_PLATFORM_WIN32) window_info.type = Core::Frontend::WindowSystemType::Windows; - window_info.render_surface = reinterpret_cast(wm.info.win.window); - break; -#endif -#ifdef SDL_VIDEO_DRIVER_X11 - case SDL_SYSWM_TYPE::SDL_SYSWM_X11: - window_info.type = Core::Frontend::WindowSystemType::X11; - window_info.display_connection = wm.info.x11.display; - window_info.render_surface = reinterpret_cast(wm.info.x11.window); - break; -#endif -#ifdef SDL_VIDEO_DRIVER_WAYLAND - case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: - window_info.type = Core::Frontend::WindowSystemType::Wayland; - window_info.display_connection = wm.info.wl.display; - window_info.render_surface = wm.info.wl.surface; - break; -#endif -#ifdef SDL_VIDEO_DRIVER_COCOA - case SDL_SYSWM_TYPE::SDL_SYSWM_COCOA: + window_info.render_surface = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); +#elif defined(SDL_PLATFORM_MACOS) window_info.type = Core::Frontend::WindowSystemType::Cocoa; window_info.render_surface = SDL_Metal_CreateView(render_window); - break; -#endif -#ifdef SDL_VIDEO_DRIVER_ANDROID - case SDL_SYSWM_TYPE::SDL_SYSWM_ANDROID: +#elif defined(SDL_PLATFORM_LINUX) + const char* video_driver = SDL_GetCurrentVideoDriver(); + if (video_driver && SDL_strcmp(video_driver, "x11") == 0) { + window_info.type = Core::Frontend::WindowSystemType::X11; + window_info.display_connection = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr); + window_info.render_surface = reinterpret_cast( + SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0)); + } else if (video_driver && SDL_strcmp(video_driver, "wayland") == 0) { + window_info.type = Core::Frontend::WindowSystemType::Wayland; + window_info.display_connection = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr); + window_info.render_surface = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr); + } else { + LOG_CRITICAL(Frontend, "Unsupported SDL video driver: {}", + video_driver ? video_driver : "(null)"); + std::exit(EXIT_FAILURE); + } +#elif defined(SDL_PLATFORM_ANDROID) window_info.type = Core::Frontend::WindowSystemType::Android; - window_info.render_surface = reinterpret_cast(wm.info.android.window); - break; -#endif - default: - LOG_CRITICAL(Frontend, "Window manager subsystem {} not implemented", wm.subsystem); + window_info.render_surface = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr); +#else + LOG_CRITICAL(Frontend, "Unsupported platform for SDL window properties"); std::exit(EXIT_FAILURE); - break; +#endif } OnResize(); @@ -88,8 +75,8 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste Common::g_scm_branch, Common::g_scm_desc); } -EmuWindow_SDL2_VK::~EmuWindow_SDL2_VK() = default; +EmuWindow_SDL3_VK::~EmuWindow_SDL3_VK() = default; -std::unique_ptr EmuWindow_SDL2_VK::CreateSharedContext() const { +std::unique_ptr EmuWindow_SDL3_VK::CreateSharedContext() const { return std::make_unique(); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h index 9467d164a4..00cc406943 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h @@ -16,11 +16,11 @@ namespace InputCommon { class InputSubsystem; } -class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { +class EmuWindow_SDL3_VK final : public EmuWindow_SDL3 { public: - explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system, + explicit EmuWindow_SDL3_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system, bool fullscreen); - ~EmuWindow_SDL2_VK() override; + ~EmuWindow_SDL3_VK() override; std::unique_ptr CreateSharedContext() const override; }; diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 4a99f34861..96689c49f6 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -346,16 +346,16 @@ int main(int argc, char** argv) { // Apply the command line arguments system.ApplySettings(); - std::unique_ptr emu_window; + std::unique_ptr emu_window; switch (Settings::values.renderer_backend.GetValue()) { case Settings::RendererBackend::OpenGL: - emu_window = std::make_unique(&input_subsystem, system, fullscreen); + emu_window = std::make_unique(&input_subsystem, system, fullscreen); break; case Settings::RendererBackend::Vulkan: - emu_window = std::make_unique(&input_subsystem, system, fullscreen); + emu_window = std::make_unique(&input_subsystem, system, fullscreen); break; case Settings::RendererBackend::Null: - emu_window = std::make_unique(&input_subsystem, system, fullscreen); + emu_window = std::make_unique(&input_subsystem, system, fullscreen); break; } From 2ab88246a07668c1d27a0b0919c2e54e4f9312e5 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 07/30] rename more macros --- .ci/windows/build.sh | 2 +- docs/Caveats.md | 2 +- docs/Deps.md | 6 +++--- docs/Options.md | 8 ++++---- externals/gamemode/gamemode_client.h | 2 +- src/audio_core/sink/sink_details.cpp | 6 +++--- src/input_common/main.cpp | 20 ++++++++++---------- src/yuzu/main.cpp | 8 ++++---- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.ci/windows/build.sh b/.ci/windows/build.sh index d554e00e1b..c0e46d219f 100644 --- a/.ci/windows/build.sh +++ b/.ci/windows/build.sh @@ -24,7 +24,7 @@ cmake .. -G Ninja \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE:-Release}" \ -DENABLE_QT_TRANSLATION=ON \ -DUSE_DISCORD_PRESENCE=ON \ - -DYUZU_USE_BUNDLED_SDL2=ON \ + -DYUZU_USE_BUNDLED_SDL3=ON \ -DBUILD_TESTING=OFF \ -DYUZU_TESTS=OFF \ -DDYNARMIC_TESTS=OFF \ diff --git a/docs/Caveats.md b/docs/Caveats.md index 7bc2428bab..b60cfd4ea9 100644 --- a/docs/Caveats.md +++ b/docs/Caveats.md @@ -38,7 +38,7 @@ export LIBGL_ALWAYS_SOFTWARE=1 ``` - Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`). -- If using OpenIndiana, due to a bug in SDL2's CMake configuration, audio driver defaults to SunOS ``, which does not exist on OpenIndiana. Using external or bundled SDL2 may solve this. +- If using OpenIndiana, due to a bug in SDL3's CMake configuration, audio driver defaults to SunOS ``, which does not exist on OpenIndiana. Using external or bundled SDL3 may solve this. - System OpenSSL generally does not work. Instead, use `-DYUZU_USE_BUNDLED_OPENSSL=ON` to use a bundled static OpenSSL, or build a system dependency from source. ## OpenBSD diff --git a/docs/Deps.md b/docs/Deps.md index 573d1fe14a..928f9b4d41 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -32,7 +32,7 @@ If you are on Windows and NOT building with MSYS2, you may go [back home](Build. The following are handled by Eden's externals: * [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`) -* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL2=ON` OR `-DYUZU_USE_BUNDLED_SDL2=ON` to reduce compile time) +* [SDL3](https://github.com/libsdl-org/SDL/releases) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL3=ON` OR `-DYUZU_USE_BUNDLED_SDL3=ON` to reduce compile time) All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only): @@ -116,7 +116,7 @@ sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel ``` * Force system libraries via CMake arguments: - * SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF` + * SDL3: `-DYUZU_USE_BUNDLED_SDL3=OFF -DYUZU_USE_EXTERNAL_SDL3=OFF` * FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF` * [RPM Fusion](https://rpmfusion.org/) is required for `ffmpeg-devel` * Fedora 32 or later is required. @@ -202,7 +202,7 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l * Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`) * Download and install all dependencies using: - * `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` + * `pacman -Syu git make mingw-w64-x86_64-SDL3 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` * Add MinGW binaries to the PATH: * `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc` * Add VulkanSDK to the PATH: diff --git a/docs/Options.md b/docs/Options.md index dc73fecd3e..7323fdc4a3 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -40,10 +40,10 @@ Notes: * Unavailable on OpenBSD The following options are desktop only: -- `ENABLE_SDL3` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) +- `ENABLE_SDL3` (ON) Enable the SDL3 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) * Unavailable on Android -- `YUZU_USE_EXTERNAL_SDL2` (ON for non-UNIX) Compiles SDL2 from source -- `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2 +- `YUZU_USE_EXTERNAL_SDL3` (ON for non-UNIX) Compiles SDL3 from source +- `YUZU_USE_BUNDLED_SDL3` (ON for MSVC) Download a prebuilt SDL3 * Unavailable on OpenBSD * Only enabled if YUZU_USE_CPM and ENABLE_SDL3 are both ON - `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED) @@ -62,7 +62,7 @@ The following options are desktop only: - `YUZU_ROOM` (ON) Enable dedicated room functionality - `YUZU_ROOM_STANDALONE` (ON) Enable standalone room executable (eden-room) * Requires `YUZU_ROOM` -- `YUZU_CMD` (ON) Compile the SDL2 frontend (eden-cli) - requires SDL2 +- `YUZU_CMD` (ON) Compile the SDL3 frontend (eden-cli) - requires SDL3 - `YUZU_CRASH_DUMPS` Compile crash dump (Minidump) support" * Currently only available on Windows and Linux diff --git a/externals/gamemode/gamemode_client.h b/externals/gamemode/gamemode_client.h index b9f64fe460..5bda6d26f8 100644 --- a/externals/gamemode/gamemode_client.h +++ b/externals/gamemode/gamemode_client.h @@ -89,7 +89,7 @@ static char internal_gamemode_client_error_string[512] = { 0 }; /** * Load libgamemode dynamically to dislodge us from most dependencies. * This allows clients to link and/or use this regardless of runtime. - * See SDL2 for an example of the reasoning behind this in terms of + * See SDL3 for an example of the reasoning behind this in terms of * dynamic versioning as well. */ static volatile int internal_libgamemode_loaded = 1; diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 70bf75018b..6076ed9eb0 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp @@ -16,7 +16,7 @@ #ifdef HAVE_CUBEB #include "audio_core/sink/cubeb_sink.h" #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 #include "audio_core/sink/sdl2_sink.h" #endif #include "audio_core/sink/null_sink.h" @@ -71,7 +71,7 @@ constexpr SinkDetails sink_details[] = { &GetCubebLatency, }, #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 SinkDetails{ Settings::AudioEngine::Sdl2, [](std::string_view device_id) -> std::unique_ptr { @@ -115,7 +115,7 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) { // BEGIN REINTRODUCED FROM 3833 - REPLACED CODE BLOCK ABOVE - DIABLO 3 FIX // Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which // causes audio issues, in that case go with SDL. -#if defined(HAVE_CUBEB) && defined(HAVE_SDL2) +#if defined(HAVE_CUBEB) && defined(HAVE_SDL3) iter = find_backend(Settings::AudioEngine::Cubeb); if (iter->latency() > TargetSampleCount * 3) { iter = find_backend(Settings::AudioEngine::Sdl2); diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 62a7ae40f8..97a86a750a 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -22,7 +22,7 @@ #ifdef HAVE_LIBUSB #include "input_common/drivers/gc_adapter.h" #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 #include "input_common/drivers/joycon.h" #include "input_common/drivers/sdl_driver.h" #endif @@ -87,7 +87,7 @@ struct InputSubsystem::Impl { #endif RegisterEngine("virtual_amiibo", virtual_amiibo); RegisterEngine("virtual_gamepad", virtual_gamepad); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 RegisterEngine("sdl", sdl); RegisterEngine("joycon", joycon); #endif @@ -121,7 +121,7 @@ struct InputSubsystem::Impl { #endif UnregisterEngine(virtual_amiibo); UnregisterEngine(virtual_gamepad); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 UnregisterEngine(sdl); UnregisterEngine(joycon); #endif @@ -151,7 +151,7 @@ struct InputSubsystem::Impl { #endif auto udp_devices = udp_client->GetInputDevices(); devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 auto joycon_devices = joycon->GetInputDevices(); devices.insert(devices.end(), joycon_devices.begin(), joycon_devices.end()); auto sdl_devices = sdl->GetInputDevices(); @@ -186,7 +186,7 @@ struct InputSubsystem::Impl { if (engine == udp_client->GetEngineName()) { return udp_client; } -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 if (engine == sdl->GetEngineName()) { return sdl; } @@ -277,7 +277,7 @@ struct InputSubsystem::Impl { if (engine == virtual_gamepad->GetEngineName()) { return true; } -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 if (engine == sdl->GetEngineName()) { return true; } @@ -298,7 +298,7 @@ struct InputSubsystem::Impl { gcadapter->BeginConfiguration(); #endif udp_client->BeginConfiguration(); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 sdl->BeginConfiguration(); joycon->BeginConfiguration(); #endif @@ -314,7 +314,7 @@ struct InputSubsystem::Impl { gcadapter->EndConfiguration(); #endif udp_client->EndConfiguration(); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 sdl->EndConfiguration(); joycon->EndConfiguration(); #endif @@ -322,7 +322,7 @@ struct InputSubsystem::Impl { void PumpEvents() const { update_engine->PumpEvents(); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 sdl->PumpEvents(); #endif } @@ -347,7 +347,7 @@ struct InputSubsystem::Impl { std::shared_ptr gcadapter; #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 std::shared_ptr sdl; std::shared_ptr joycon; #endif diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 58c1b151e2..a80177a038 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -95,7 +95,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include #include -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 #include #include #include // For SDL ScreenSaver functions @@ -584,7 +584,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) VkDeviceInfo::PopulateRecords(vk_device_records, this->window()->windowHandle()); } -#if defined(HAVE_SDL2) && !defined(_WIN32) +#if defined(HAVE_SDL3) && !defined(_WIN32) SDL_InitSubSystem(SDL_INIT_VIDEO); // Set a screensaver inhibition reason string. Currently passed to DBus by SDL and visible to @@ -1855,7 +1855,7 @@ void GMainWindow::OnSigInterruptNotifierActivated() { void GMainWindow::PreventOSSleep() { #ifdef _WIN32 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); -#elif defined(HAVE_SDL2) +#elif defined(HAVE_SDL3) SDL_DisableScreenSaver(); #endif } @@ -1863,7 +1863,7 @@ void GMainWindow::PreventOSSleep() { void GMainWindow::AllowOSSleep() { #ifdef _WIN32 SetThreadExecutionState(ES_CONTINUOUS); -#elif defined(HAVE_SDL2) +#elif defined(HAVE_SDL3) SDL_EnableScreenSaver(); #endif } From 726fe8cf09d7f41a58df3bcc22a63f92db9900d0 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:02:49 +0200 Subject: [PATCH 08/30] repo name typo --- cpmfile.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpmfile.json b/cpmfile.json index 8c596b67ba..84df8420fc 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -177,7 +177,7 @@ "ci": true, "package": "SDL3", "name": "SDL3", - "repo": "libsdl-org/SDL3", + "repo": "libsdl-org/SDL", "version": "3.2.22", "min_version": "3.2.0", "cmake_filename": "sdl3" From 36733267fd2feb92f723a37e5f1c5f0ae09da4a3 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:11:55 +0200 Subject: [PATCH 09/30] rename remaining files and vars --- docs/Deps.md | 10 +++++----- src/audio_core/CMakeLists.txt | 4 ++-- .../sink/{sdl2_sink.cpp => sdl3_sink.cpp} | 2 +- src/audio_core/sink/{sdl2_sink.h => sdl3_sink.h} | 0 src/audio_core/sink/sink_details.cpp | 6 +++--- src/common/settings_enums.h | 4 ++-- src/frontend_common/config.cpp | 2 +- src/yuzu_cmd/CMakeLists.txt | 16 ++++++++-------- .../{emu_window_sdl2.cpp => emu_window_sdl3.cpp} | 2 +- .../{emu_window_sdl2.h => emu_window_sdl3.h} | 0 ...window_sdl2_gl.cpp => emu_window_sdl3_gl.cpp} | 2 +- ...emu_window_sdl2_gl.h => emu_window_sdl3_gl.h} | 2 +- ...ow_sdl2_null.cpp => emu_window_sdl3_null.cpp} | 2 +- ...window_sdl2_null.h => emu_window_sdl3_null.h} | 2 +- ...window_sdl2_vk.cpp => emu_window_sdl3_vk.cpp} | 2 +- ...emu_window_sdl2_vk.h => emu_window_sdl3_vk.h} | 2 +- src/yuzu_cmd/yuzu.cpp | 8 ++++---- 17 files changed, 33 insertions(+), 33 deletions(-) rename src/audio_core/sink/{sdl2_sink.cpp => sdl3_sink.cpp} (99%) rename src/audio_core/sink/{sdl2_sink.h => sdl3_sink.h} (100%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2.cpp => emu_window_sdl3.cpp} (99%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2.h => emu_window_sdl3.h} (100%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_gl.cpp => emu_window_sdl3_gl.cpp} (98%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_gl.h => emu_window_sdl3_gl.h} (95%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_null.cpp => emu_window_sdl3_null.cpp} (96%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_null.h => emu_window_sdl3_null.h} (92%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_vk.cpp => emu_window_sdl3_vk.cpp} (98%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_vk.h => emu_window_sdl3_vk.h} (92%) diff --git a/docs/Deps.md b/docs/Deps.md index 928f9b4d41..b58b6ee053 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -89,7 +89,7 @@ Click on the arrows to expand. Arch Linux ```sh -sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip zydis zycore vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers +sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl3 zlib zstd zip unzip zydis zycore vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers ``` * Building with QT Web Engine requires `qt6-webengine` as well. @@ -129,7 +129,7 @@ sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel Install dependencies from **[Homebrew](https://brew.sh/)** ```sh -brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools +brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl3 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools ``` If you are compiling on Intel Mac, or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` with `/usr/local`. @@ -146,7 +146,7 @@ brew install molten-vk vulkan-loader ``` devel/cmake -devel/sdl20 +devel/sdl30 devel/boost-libs devel/catch2 devel/libfmt @@ -180,7 +180,7 @@ If using FreeBSD 12 or prior, use `devel/pkg-config` instead. ```sh pkg_add -u -pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl2 libusb1.1.0.27 +pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl3 libusb1.1.0.27 ``` @@ -194,7 +194,7 @@ Run the usual update + install of essential toolings: `sudo pkg update && sudo p - **gcc**: `sudo pkg install developer/gcc-14`. - **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`. -Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`. +Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl3 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`.
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 77ac05c7a2..23ffe7f053 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -249,8 +249,8 @@ endif() if (ENABLE_SDL3) target_sources(audio_core PRIVATE - sink/sdl2_sink.cpp - sink/sdl2_sink.h + sink/sdl3_sink.cpp + sink/sdl3_sink.h ) target_link_libraries(audio_core PRIVATE SDL3::SDL3) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl3_sink.cpp similarity index 99% rename from src/audio_core/sink/sdl2_sink.cpp rename to src/audio_core/sink/sdl3_sink.cpp index 2d07a35c43..563fe0f0ce 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl3_sink.cpp @@ -11,7 +11,7 @@ #include #include "audio_core/common/common.h" -#include "audio_core/sink/sdl2_sink.h" +#include "audio_core/sink/sdl3_sink.h" #include "audio_core/sink/sink_stream.h" #include "common/logging/log.h" #include "core/core.h" diff --git a/src/audio_core/sink/sdl2_sink.h b/src/audio_core/sink/sdl3_sink.h similarity index 100% rename from src/audio_core/sink/sdl2_sink.h rename to src/audio_core/sink/sdl3_sink.h diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 6076ed9eb0..3c2b3bf9c6 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp @@ -17,7 +17,7 @@ #include "audio_core/sink/cubeb_sink.h" #endif #ifdef HAVE_SDL3 -#include "audio_core/sink/sdl2_sink.h" +#include "audio_core/sink/sdl3_sink.h" #endif #include "audio_core/sink/null_sink.h" #include "common/logging/log.h" @@ -73,7 +73,7 @@ constexpr SinkDetails sink_details[] = { #endif #ifdef HAVE_SDL3 SinkDetails{ - Settings::AudioEngine::Sdl2, + Settings::AudioEngine::Sdl3, [](std::string_view device_id) -> std::unique_ptr { return std::make_unique(device_id); }, @@ -118,7 +118,7 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) { #if defined(HAVE_CUBEB) && defined(HAVE_SDL3) iter = find_backend(Settings::AudioEngine::Cubeb); if (iter->latency() > TargetSampleCount * 3) { - iter = find_backend(Settings::AudioEngine::Sdl2); + iter = find_backend(Settings::AudioEngine::Sdl3); } #else iter = std::begin(sink_details); diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 0e5a08d845..89fc83299c 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -92,11 +92,11 @@ struct EnumMetadata { // AudioEngine must be specified discretely due to having existing but slightly different // canonicalizations // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id -enum class AudioEngine : u32 { Auto, Cubeb, Sdl2, Null, Oboe, }; +enum class AudioEngine : u32 { Auto, Cubeb, Sdl3, Null, Oboe, }; template<> inline std::vector> EnumMetadata::Canonicalizations() { return { - {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2}, + {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl3", AudioEngine::Sdl3}, {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe}, }; } diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp index fa1383436e..a0b2af5c8c 100644 --- a/src/frontend_common/config.cpp +++ b/src/frontend_common/config.cpp @@ -51,7 +51,7 @@ void Config::Initialize(const std::string& config_name) { void Config::Initialize(const std::optional config_path) { const std::filesystem::path default_sdl_config_path = - FS::GetEdenPath(FS::EdenPath::ConfigDir) / "sdl2-config.ini"; + FS::GetEdenPath(FS::EdenPath::ConfigDir) / "sdl3-config.ini"; config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path)); void(FS::CreateParentDir(config_loc)); SetUpIni(); diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index 47e0f7e5e1..f62f4b49e3 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -16,14 +16,14 @@ function(create_resource file output filename) endfunction() add_executable(yuzu-cmd - emu_window/emu_window_sdl2.cpp - emu_window/emu_window_sdl2.h - emu_window/emu_window_sdl2_gl.cpp - emu_window/emu_window_sdl2_gl.h - emu_window/emu_window_sdl2_null.cpp - emu_window/emu_window_sdl2_null.h - emu_window/emu_window_sdl2_vk.cpp - emu_window/emu_window_sdl2_vk.h + emu_window/emu_window_sdl3.cpp + emu_window/emu_window_sdl3.h + emu_window/emu_window_sdl3_gl.cpp + emu_window/emu_window_sdl3_gl.h + emu_window/emu_window_sdl3_null.cpp + emu_window/emu_window_sdl3_null.h + emu_window/emu_window_sdl3_vk.cpp + emu_window/emu_window_sdl3_vk.h precompiled_headers.h sdl_config.cpp sdl_config.h diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp similarity index 99% rename from src/yuzu_cmd/emu_window/emu_window_sdl2.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3.cpp index 38754fe7f0..5988c130c0 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp @@ -16,7 +16,7 @@ #include "input_common/drivers/mouse.h" #include "input_common/drivers/touch_screen.h" #include "input_common/main.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" #include "yuzu_cmd/yuzu_icon.h" EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl3.h similarity index 100% rename from src/yuzu_cmd/emu_window/emu_window_sdl2.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3.h diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.cpp similarity index 98% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3_gl.cpp index 4e00fa91a8..6eb9c1445c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.cpp @@ -18,7 +18,7 @@ #include "core/core.h" #include "input_common/main.h" #include "video_core/renderer_base.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_gl.h" class SDLGLContext : public Core::Frontend::GraphicsContext { public: diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.h similarity index 95% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3_gl.h index 345ee17760..5b664d5314 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.h @@ -6,7 +6,7 @@ #include #include #include "core/frontend/emu_window.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" namespace Core { class System; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.cpp similarity index 96% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3_null.cpp index 36f61bd6f1..0704862061 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.cpp @@ -10,7 +10,7 @@ #include "common/logging/log.h" #include "common/scm_rev.h" #include "video_core/renderer_null/renderer_null.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_null.h" #ifdef YUZU_USE_EXTERNAL_SDL3 // Include this before SDL.h to prevent the external from including a dummy diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.h similarity index 92% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_null.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3_null.h index f194d137ae..6f43cc7997 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.h @@ -6,7 +6,7 @@ #include #include "core/frontend/emu_window.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" namespace Core { class System; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.cpp similarity index 98% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3_vk.cpp index ee43f130ce..dada5d308e 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.cpp @@ -9,7 +9,7 @@ #include "common/logging/log.h" #include "common/scm_rev.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_vk.h" #include diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.h similarity index 92% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3_vk.h index 00cc406943..df6fc391ad 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.h @@ -6,7 +6,7 @@ #include #include "core/frontend/emu_window.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" namespace Core { class System; diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 96689c49f6..68c1edeaed 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -34,10 +34,10 @@ #include "network/network.h" #include "sdl_config.h" #include "video_core/renderer_base.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_gl.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_null.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_vk.h" #ifdef _WIN32 // windows.h needs to be included before shellapi.h From cd831989d9fb96b96b693e58a330eb4eca6b924b Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:17:52 +0200 Subject: [PATCH 10/30] remove steamdeck sdl dep --- CMakeLists.txt | 7 +------ cpmfile.json | 8 -------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a690ebd119..da4363308b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -633,12 +633,7 @@ if (ENABLE_SDL3) set(SDL_FILE ON) endif() - if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") - set(SDL_PIPEWIRE OFF) # build errors out with this on - AddJsonPackage("sdl3_steamdeck") - else() - AddJsonPackage("sdl3_generic") - endif() + AddJsonPackage("sdl3_generic") elseif (YUZU_USE_BUNDLED_SDL3) message(STATUS "Using bundled SDL3") AddJsonPackage(sdl3) diff --git a/cpmfile.json b/cpmfile.json index 84df8420fc..fdaa17b7b3 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -165,14 +165,6 @@ "key": "generic", "bundled": true }, - "sdl3_steamdeck": { - "package": "SDL3", - "repo": "libsdl-org/SDL", - "sha": "cc016b0046", - "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", - "key": "steamdeck", - "bundled": true - }, "sdl3": { "ci": true, "package": "SDL3", From a8b6d13bc3e8ce307555dcf93300117bc0d54c4a Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:18:09 +0200 Subject: [PATCH 11/30] do not require latest --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da4363308b..ae300cc4bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -639,7 +639,7 @@ if (ENABLE_SDL3) AddJsonPackage(sdl3) endif() - find_package(SDL3 3.2.22 REQUIRED) + find_package(SDL3 3.2.12 REQUIRED) endif() # List of all FFmpeg components required From 2453a597c8fc4339e6fac4512c4befd2b476752f Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:22:19 +0200 Subject: [PATCH 12/30] doc typos --- docs/Deps.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Deps.md b/docs/Deps.md index b58b6ee053..49f72b7b97 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -32,7 +32,7 @@ If you are on Windows and NOT building with MSYS2, you may go [back home](Build. The following are handled by Eden's externals: * [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`) -* [SDL3](https://github.com/libsdl-org/SDL/releases) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL3=ON` OR `-DYUZU_USE_BUNDLED_SDL3=ON` to reduce compile time) +* [SDL3](https://github.com/libsdl-org/SDL/releases) 3.2.12+ (should use `-DYUZU_USE_EXTERNAL_SDL3=ON` OR `-DYUZU_USE_BUNDLED_SDL3=ON` to reduce compile time) All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only): @@ -202,7 +202,7 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l * Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`) * Download and install all dependencies using: - * `pacman -Syu git make mingw-w64-x86_64-SDL3 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` + * `pacman -Syu git make mingw-w64-x86_64-sdl3 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` * Add MinGW binaries to the PATH: * `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc` * Add VulkanSDK to the PATH: From af6c90e3ffee657a4892b53d7d00c87efa368201 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:22:59 +0200 Subject: [PATCH 13/30] unused include --- src/input_common/drivers/sdl_driver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index d140b00ca0..fb3e376c63 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -8,7 +8,6 @@ #include "common/param_package.h" #include "common/settings.h" #include "common/thread.h" -// #include "common/vector_math.h" // Not used directly #include "input_common/drivers/sdl_driver.h" namespace InputCommon { From 76b5d6778ec6245979a9f6963616d7fadb814d76 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 1 Oct 2025 23:18:37 +0200 Subject: [PATCH 14/30] [common/logging] faster logging by avoiding constructing unused strings/results (and filtering first) (#2603) basically std::string would be invoked even when the logging was filtered, then destroyed instantly, invoking malloc/free and polluting mem arenas for no good reason Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2603 Reviewed-by: MaranBr Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/logging/backend.cpp | 38 +++++++++++-------- src/common/logging/filter.cpp | 26 ++++++------- src/common/logging/log.h | 21 +++------- .../hle/service/ssl/ssl_backend_openssl.cpp | 5 ++- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 4621771090..c2cbf3f4a5 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -39,9 +39,17 @@ namespace Common::Log { namespace { -/** - * Interface for logging backends. - */ +/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string +/// do not be fooled this isn't generating new strings on .rodata :) +constexpr const char* TrimSourcePath(std::string_view source) { + const auto rfind = [source](const std::string_view match) { + return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size()); + }; + auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")}); + return source.data() + idx; +} + +/// @brief Interface for logging backends. class Backend { public: virtual ~Backend() = default; @@ -53,9 +61,7 @@ public: virtual void Flush() = 0; }; -/** - * Backend that writes to stderr and with color - */ +/// @brief Backend that writes to stderr and with color class ColorConsoleBackend final : public Backend { public: explicit ColorConsoleBackend() = default; @@ -84,9 +90,7 @@ private: std::atomic_bool enabled{false}; }; -/** - * Backend that writes to a file passed into the constructor - */ +/// @brief Backend that writes to a file passed into the constructor class FileBackend final : public Backend { public: explicit FileBackend(const std::filesystem::path& filename) { @@ -248,13 +252,14 @@ public: color_console_backend.SetEnabled(enabled); } + bool CanPushEntry(Class log_class, Level log_level) const noexcept { + return filter.CheckMessage(log_class, log_level); + } + void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, - const char* function, std::string&& message) { - if (!filter.CheckMessage(log_class, log_level)) { - return; - } + const char* function, std::string&& message) noexcept { message_queue.EmplaceWait( - CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); + CreateEntry(log_class, log_level, TrimSourcePath(filename), line_num, function, std::move(message))); } private: @@ -368,8 +373,9 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) { if (!initialization_in_progress_suppress_logging) { - Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, - fmt::vformat(format, args)); + auto& instance = Impl::Instance(); + if (instance.CanPushEntry(log_class, log_level)) + instance.PushEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); } } } // namespace Common::Log diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 4e3a614a45..813e812780 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -9,22 +12,20 @@ namespace Common::Log { namespace { template Level GetLevelByName(const It begin, const It end) { - for (u8 i = 0; i < static_cast(Level::Count); ++i) { - const char* level_name = GetLevelName(static_cast(i)); - if (Common::ComparePartialString(begin, end, level_name)) { - return static_cast(i); - } + for (u32 i = 0; i < u32(Level::Count); ++i) { + const char* level_name = GetLevelName(Level(i)); + if (Common::ComparePartialString(begin, end, level_name)) + return Level(i); } return Level::Count; } template Class GetClassByName(const It begin, const It end) { - for (u8 i = 0; i < static_cast(Class::Count); ++i) { - const char* level_name = GetLogClassName(static_cast(i)); - if (Common::ComparePartialString(begin, end, level_name)) { - return static_cast(i); - } + for (u32 i = 0; i < u32(Class::Count); ++i) { + const char* level_name = GetLogClassName(Class(i)); + if (Common::ComparePartialString(begin, end, level_name)) + return Class(i); } return Class::Count; } @@ -229,13 +230,12 @@ void Filter::ParseFilterString(std::string_view filter_view) { } bool Filter::CheckMessage(Class log_class, Level level) const { - return static_cast(level) >= - static_cast(class_levels[static_cast(log_class)]); + return u8(level) >= u8(class_levels[std::size_t(log_class)]); } bool Filter::IsDebug() const { return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) { - return static_cast(l) <= static_cast(Level::Debug); + return u8(l) <= u8(Level::Debug); }); } diff --git a/src/common/logging/log.h b/src/common/logging/log.h index bd7a7d7f49..7b23b59aab 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -16,15 +16,6 @@ namespace Common::Log { -// trims up to and including the last of ../, ..\, src/, src\ in a string -constexpr const char* TrimSourcePath(std::string_view source) { - const auto rfind = [source](const std::string_view match) { - return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size()); - }; - auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")}); - return source.data() + idx; -} - /// Logs a message to the global logger, using fmt void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, @@ -42,7 +33,7 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig #ifdef _DEBUG #define LOG_TRACE(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \ - Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __FILE__, __LINE__, __func__, \ __VA_ARGS__) #else #define LOG_TRACE(log_class, fmt, ...) (void(0)) @@ -50,21 +41,21 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig #define LOG_DEBUG(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \ - Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __FILE__, __LINE__, __func__, \ __VA_ARGS__) #define LOG_INFO(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \ - Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __FILE__, __LINE__, __func__, \ __VA_ARGS__) #define LOG_WARNING(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \ - Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __FILE__, __LINE__, __func__, \ __VA_ARGS__) #define LOG_ERROR(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \ - Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __FILE__, __LINE__, __func__, \ __VA_ARGS__) #define LOG_CRITICAL(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \ - Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __FILE__, __LINE__, __func__, \ __VA_ARGS__) diff --git a/src/core/hle/service/ssl/ssl_backend_openssl.cpp b/src/core/hle/service/ssl/ssl_backend_openssl.cpp index 5714e6f3c5..795b69a873 100644 --- a/src/core/hle/service/ssl/ssl_backend_openssl.cpp +++ b/src/core/hle/service/ssl/ssl_backend_openssl.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -286,7 +289,7 @@ Result CheckOpenSSLErrors() { msg.append(data); } Common::Log::FmtLogMessage(Common::Log::Class::Service_SSL, Common::Log::Level::Error, - Common::Log::TrimSourcePath(file), line, func, "OpenSSL: {}", + file, line, func, "OpenSSL: {}", msg); } return ResultInternalError; From 326865cba2641f693d8500506594c387259dfc11 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Thu, 2 Oct 2025 00:15:14 +0200 Subject: [PATCH 15/30] [host1x] Improve FFmpeg error handling (#2643) This improves the FFmpeg error handling. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2643 Co-authored-by: MaranBr Co-committed-by: MaranBr --- .../nvdrv/devices/nvhost_nvdec_common.cpp | 4 ++-- src/video_core/host1x/codecs/decoder.cpp | 4 ++++ src/video_core/host1x/ffmpeg/ffmpeg.cpp | 22 +++++++++---------- src/video_core/host1x/ffmpeg/ffmpeg.h | 2 +- src/video_core/host1x/vic.cpp | 5 +++++ 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index de4197c52d..f7d6c33f77 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -135,8 +135,8 @@ NvResult nvhost_nvdec_common::GetSyncpoint(IoctlGetSyncpoint& params) { } NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { - LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); - params.value = 0; // Seems to be hard coded at 0 + LOG_DEBUG(Service_NVDRV, "called WAITBASE"); + params.value = 0; return NvResult::Success; } diff --git a/src/video_core/host1x/codecs/decoder.cpp b/src/video_core/host1x/codecs/decoder.cpp index cb17784b19..887eb28c8c 100755 --- a/src/video_core/host1x/codecs/decoder.cpp +++ b/src/video_core/host1x/codecs/decoder.cpp @@ -38,6 +38,10 @@ void Decoder::Decode() { // Receive output frames from decoder. auto frame = decode_api.ReceiveFrame(); + if (!frame) { + return; + } + if (IsInterlaced()) { auto [luma_top, luma_bottom, chroma_top, chroma_bottom] = GetInterlacedOffsets(); auto frame_copy = frame; diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp index 536a01fcc8..bbbbe615ce 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp +++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp @@ -233,7 +233,7 @@ bool DecoderContext::OpenContext(const Decoder& decoder) { } bool DecoderContext::SendPacket(const Packet& packet) { - if (const int ret = avcodec_send_packet(m_codec_context, packet.GetPacket()); ret < 0 && ret != AVERROR_EOF) { + if (const int ret = avcodec_send_packet(m_codec_context, packet.GetPacket()); ret < 0 && ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) { LOG_ERROR(HW_GPU, "avcodec_send_packet error: {}", AVError(ret)); return false; } @@ -242,31 +242,31 @@ bool DecoderContext::SendPacket(const Packet& packet) { } std::shared_ptr DecoderContext::ReceiveFrame() { - auto ReceiveImpl = [&](AVFrame* frame) -> bool { - if (const int ret = avcodec_receive_frame(m_codec_context, frame); ret < 0 && ret != AVERROR_EOF) { + auto ReceiveImpl = [&](AVFrame* frame) -> int { + const int ret = avcodec_receive_frame(m_codec_context, frame); + if (ret < 0 && ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) { LOG_ERROR(HW_GPU, "avcodec_receive_frame error: {}", AVError(ret)); - return false; } - return true; + return ret; }; std::shared_ptr intermediate_frame = std::make_shared(); - if (!ReceiveImpl(intermediate_frame->GetFrame())) { + if (ReceiveImpl(intermediate_frame->GetFrame()) < 0) { return {}; } - m_temp_frame = std::make_shared(); + m_final_frame = std::make_shared(); if (m_codec_context->hw_device_ctx) { - m_temp_frame->SetFormat(PreferredGpuFormat); - if (int ret = av_hwframe_transfer_data(m_temp_frame->GetFrame(), intermediate_frame->GetFrame(), 0); ret < 0) { + m_final_frame->SetFormat(PreferredGpuFormat); + if (const int ret = av_hwframe_transfer_data(m_final_frame->GetFrame(), intermediate_frame->GetFrame(), 0); ret < 0) { LOG_ERROR(HW_GPU, "av_hwframe_transfer_data error: {}", AVError(ret)); return {}; } } else { - m_temp_frame = std::move(intermediate_frame); + m_final_frame = std::move(intermediate_frame); } - return std::move(m_temp_frame); + return std::move(m_final_frame); } void DecodeApi::Reset() { diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.h b/src/video_core/host1x/ffmpeg/ffmpeg.h index 0dd7c7cb04..d60a8ac4a7 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.h +++ b/src/video_core/host1x/ffmpeg/ffmpeg.h @@ -194,7 +194,7 @@ public: private: const Decoder& m_decoder; AVCodecContext* m_codec_context{}; - std::shared_ptr m_temp_frame{}; + std::shared_ptr m_final_frame{}; bool m_decode_order{}; }; diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 9c33370337..3dbbfa5552 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -146,6 +146,11 @@ void Vic::Execute() { } auto frame = frame_queue.GetFrame(nvdec_id, luma_offset); + + if (!frame) { + continue; + } + if (!frame.get()) { LOG_ERROR(HW_GPU, "Vic {} failed to get frame with offset {:#X}", id, luma_offset); continue; From 24e6c62109cd30e09dd72a4af58f132dd7c0d359 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 2 Oct 2025 00:25:41 +0200 Subject: [PATCH 16/30] [vk, ogl] invalidate pipeline caches from <=0.0.3 (#2637) Invalidates caches before next upcoming release, this will make transitions smoother especially for users whom do not know how to clear caches. The reasoning behind this is the recent changes to async shaders and other pipeline stuffs that may break compat Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2637 Reviewed-by: MaranBr Reviewed-by: Maufeat Co-authored-by: lizzie Co-committed-by: lizzie --- src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 +- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index c2ead26bd9..45f729698e 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -54,7 +54,7 @@ using VideoCommon::LoadPipelines; using VideoCommon::SerializePipeline; using Context = ShaderContext::Context; -constexpr u32 CACHE_VERSION = 10; +constexpr u32 CACHE_VERSION = 13; template auto MakeSpan(Container& container) { diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 2fd0b59b3a..9cdbe5611b 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -55,7 +55,7 @@ using VideoCommon::FileEnvironment; using VideoCommon::GenericEnvironment; using VideoCommon::GraphicsEnvironment; -constexpr u32 CACHE_VERSION = 12; +constexpr u32 CACHE_VERSION = 13; constexpr std::array VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'}; template From 1a5b3fb23934cfb9647120fc2a055bc116e67460 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Thu, 2 Oct 2025 01:30:05 +0200 Subject: [PATCH 17/30] [audio_core] Fix audio reverb effect (#2646) This fixes the audio reverb effect that was causing loud noise in some games and on some platforms. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2646 Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/audio_core/renderer/behavior/info_updater.cpp | 12 ------------ src/audio_core/renderer/command/effect/reverb.cpp | 2 -- 2 files changed, 14 deletions(-) diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp index 48fe1f8975..20f6cda3a2 100644 --- a/src/audio_core/renderer/behavior/info_updater.cpp +++ b/src/audio_core/renderer/behavior/info_updater.cpp @@ -165,12 +165,6 @@ Result InfoUpdater::UpdateEffectsVersion1(EffectContext& effect_context, const b reinterpret_cast(output), effect_count}; for (u32 i = 0; i < effect_count; i++) { -#ifdef _WIN32 - // There's a bug in Windows where using this effect causes extreme noise. So let's skip it. - if (in_params[i].type == EffectInfoBase::Type::Reverb) { - continue; - } -#endif auto effect_info{&effect_context.GetInfo(i)}; if (effect_info->GetType() != in_params[i].type) { effect_info->ForceUnmapBuffers(pool_mapper); @@ -218,12 +212,6 @@ Result InfoUpdater::UpdateEffectsVersion2(EffectContext& effect_context, const b reinterpret_cast(output), effect_count}; for (u32 i = 0; i < effect_count; i++) { -#ifdef _WIN32 - // There's a bug in Windows where using this effect causes extreme noise. So let's skip it. - if (in_params[i].type == EffectInfoBase::Type::Reverb) { - continue; - } -#endif auto effect_info{&effect_context.GetInfo(i)}; if (effect_info->GetType() != in_params[i].type) { effect_info->ForceUnmapBuffers(pool_mapper); diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index 46b85b8945..87eab1adda 100644 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -191,8 +191,6 @@ static void InitializeReverbEffect(const ReverbInfo::ParameterVersion2& params, const auto center_delay_time{(5 * delay).to_uint_floor()}; state.center_delay_line.Initialize(center_delay_time, 1.0f); - UpdateReverbEffectParameter(params, state); - for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) { std::ranges::fill(state.fdn_delay_lines[i].buffer, 0); std::ranges::fill(state.decay_delay_lines[i].buffer, 0); From 0b74d1cebba58c6428da294f6f6da7fdfdc9b83e Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 18/30] switch to SDL3 dep --- .ci/linux/build.sh | 4 +-- CMakeLists.txt | 34 +++++++++---------- CMakeModules/CopyYuzuSDLDeps.cmake | 2 +- CMakeModules/MinGWClangCross.cmake | 2 +- CMakeModules/MinGWCross.cmake | 2 +- cpmfile.json | 26 +++++++------- docs/Options.md | 4 +-- src/CMakeLists.txt | 2 +- src/android/app/build.gradle.kts | 2 +- src/audio_core/CMakeLists.txt | 6 ++-- src/audio_core/sink/sdl2_sink.cpp | 2 +- src/input_common/CMakeLists.txt | 6 ++-- src/input_common/drivers/sdl_driver.h | 2 +- src/yuzu/CMakeLists.txt | 6 ++-- src/yuzu/main.cpp | 2 +- src/yuzu_cmd/CMakeLists.txt | 2 +- src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 2 +- .../emu_window/emu_window_sdl2_gl.cpp | 2 +- .../emu_window/emu_window_sdl2_null.cpp | 2 +- .../emu_window/emu_window_sdl2_vk.cpp | 2 +- src/yuzu_cmd/sdl_config.cpp | 2 +- 21 files changed, 57 insertions(+), 57 deletions(-) diff --git a/.ci/linux/build.sh b/.ci/linux/build.sh index 41e0ca308b..f46dd9bdf1 100755 --- a/.ci/linux/build.sh +++ b/.ci/linux/build.sh @@ -97,8 +97,8 @@ cmake .. -G Ninja \ -DCMAKE_CXX_FLAGS="$ARCH_FLAGS" \ -DCMAKE_C_FLAGS="$ARCH_FLAGS" \ -DYUZU_USE_BUNDLED_QT=OFF \ - -DYUZU_USE_BUNDLED_SDL2=OFF \ - -DYUZU_USE_EXTERNAL_SDL2=ON \ + -DYUZU_USE_BUNDLED_SDL3=OFF \ + -DYUZU_USE_EXTERNAL_SDL3=ON \ -DYUZU_TESTS=OFF \ -DYUZU_USE_QT_MULTIMEDIA=$MULTIMEDIA \ -DYUZU_USE_QT_WEB_ENGINE=$WEBENGINE \ diff --git a/CMakeLists.txt b/CMakeLists.txt index a9ff2e9458..a690ebd119 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,14 +137,14 @@ if (PLATFORM_FREEBSD) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") endif() -# Set bundled sdl2/qt as dependent options. -# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion -cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) +# Set bundled sdl3/qt as dependent options. +# On Linux system SDL3 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion +cmake_dependent_option(ENABLE_SDL3 "Enable the SDL3 frontend" ON "NOT ANDROID" OFF) -if (ENABLE_SDL2) +if (ENABLE_SDL3) # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system - cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) - option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") + cmake_dependent_option(YUZU_USE_EXTERNAL_SDL3 "Compile external SDL3" OFF "NOT MSVC" OFF) + option(YUZU_USE_BUNDLED_SDL3 "Download bundled SDL3 build" "${MSVC}") endif() option(ENABLE_QT "Enable the Qt frontend" ON) @@ -215,7 +215,7 @@ option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) -cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) +cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL3;NOT ANDROID" OFF) cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) @@ -609,10 +609,10 @@ if(ENABLE_CUBEB) endif() endif() -# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package -if (ENABLE_SDL2) - if (YUZU_USE_EXTERNAL_SDL2) - message(STATUS "Using SDL2 from externals.") +# find SDL3 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package +if (ENABLE_SDL3) + if (YUZU_USE_EXTERNAL_SDL3) + message(STATUS "Using SDL3 from externals.") if (NOT WIN32) # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) @@ -635,16 +635,16 @@ if (ENABLE_SDL2) if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") set(SDL_PIPEWIRE OFF) # build errors out with this on - AddJsonPackage("sdl2_steamdeck") + AddJsonPackage("sdl3_steamdeck") else() - AddJsonPackage("sdl2_generic") + AddJsonPackage("sdl3_generic") endif() - elseif (YUZU_USE_BUNDLED_SDL2) - message(STATUS "Using bundled SDL2") - AddJsonPackage(sdl2) + elseif (YUZU_USE_BUNDLED_SDL3) + message(STATUS "Using bundled SDL3") + AddJsonPackage(sdl3) endif() - find_package(SDL2 2.26.4 REQUIRED) + find_package(SDL3 3.2.22 REQUIRED) endif() # List of all FFmpeg components required diff --git a/CMakeModules/CopyYuzuSDLDeps.cmake b/CMakeModules/CopyYuzuSDLDeps.cmake index 464eed5e9c..c3935794ca 100644 --- a/CMakeModules/CopyYuzuSDLDeps.cmake +++ b/CMakeModules/CopyYuzuSDLDeps.cmake @@ -4,5 +4,5 @@ function(copy_yuzu_SDL_deps target_dir) include(WindowsCopyFiles) set(DLL_DEST "$/") - windows_copy_files(${target_dir} ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll) + windows_copy_files(${target_dir} ${SDL3_DLL_DIR} ${DLL_DEST} SDL3.dll) endfunction(copy_yuzu_SDL_deps) diff --git a/CMakeModules/MinGWClangCross.cmake b/CMakeModules/MinGWClangCross.cmake index 286a59a7ad..11ed402380 100644 --- a/CMakeModules/MinGWClangCross.cmake +++ b/CMakeModules/MinGWClangCross.cmake @@ -6,7 +6,7 @@ set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) -set(SDL2_PATH ${MINGW_PREFIX}) +set(SDL3_PATH ${MINGW_PREFIX}) set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-) # Specify the cross compiler diff --git a/CMakeModules/MinGWCross.cmake b/CMakeModules/MinGWCross.cmake index 61464f7dae..5cebe81a6e 100644 --- a/CMakeModules/MinGWCross.cmake +++ b/CMakeModules/MinGWCross.cmake @@ -9,7 +9,7 @@ set(CMAKE_HOST_WIN32 TRUE) set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) -set(SDL2_PATH ${MINGW_PREFIX}) +set(SDL3_PATH ${MINGW_PREFIX}) set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-) # Specify the cross compiler diff --git a/cpmfile.json b/cpmfile.json index f1fd5ce1cf..8c596b67ba 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -157,30 +157,30 @@ "hash": "99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c", "find_args": "MODULE" }, - "sdl2_generic": { - "package": "SDL2", + "sdl3_generic": { + "package": "SDL3", "repo": "libsdl-org/SDL", - "sha": "54772f345a", - "hash": "2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4", + "sha": "a96677bdf6", + "hash": "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "key": "generic", "bundled": true }, - "sdl2_steamdeck": { - "package": "SDL2", + "sdl3_steamdeck": { + "package": "SDL3", "repo": "libsdl-org/SDL", "sha": "cc016b0046", "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", "key": "steamdeck", "bundled": true }, - "sdl2": { + "sdl3": { "ci": true, - "package": "SDL2", - "name": "SDL2", - "repo": "crueter-ci/SDL2", - "version": "2.32.8", - "min_version": "2.26.4", - "cmake_filename": "sdl2" + "package": "SDL3", + "name": "SDL3", + "repo": "libsdl-org/SDL3", + "version": "3.2.22", + "min_version": "3.2.0", + "cmake_filename": "sdl3" }, "llvm-mingw": { "repo": "misc/llvm-mingw", diff --git a/docs/Options.md b/docs/Options.md index 3dd84ea645..dc73fecd3e 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -40,12 +40,12 @@ Notes: * Unavailable on OpenBSD The following options are desktop only: -- `ENABLE_SDL2` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) +- `ENABLE_SDL3` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) * Unavailable on Android - `YUZU_USE_EXTERNAL_SDL2` (ON for non-UNIX) Compiles SDL2 from source - `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2 * Unavailable on OpenBSD - * Only enabled if YUZU_USE_CPM and ENABLE_SDL2 are both ON + * Only enabled if YUZU_USE_CPM and ENABLE_SDL3 are both ON - `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED) - `ENABLE_OPENGL` (ON) Enable the OpenGL graphics frontend * Unavailable on Windows/ARM64 and Android diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 88470c4c42..ed209890ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -223,7 +223,7 @@ if (YUZU_TESTS) add_subdirectory(tests) endif() -if (ENABLE_SDL2 AND YUZU_CMD) +if (ENABLE_SDL3 AND YUZU_CMD) add_subdirectory(yuzu_cmd) set_target_properties(yuzu-cmd PROPERTIES OUTPUT_NAME "eden-cli") endif() diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index e8d8141711..8dedf35446 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -168,7 +168,7 @@ android { cmake { arguments( "-DENABLE_QT=0", // Don't use QT - "-DENABLE_SDL2=0", // Don't use SDL + "-DENABLE_SDL3=0", // Don't use SDL "-DENABLE_WEB_SERVICE=1", // Enable web service "-DENABLE_OPENSSL=ON", "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index c9f8af7dc3..77ac05c7a2 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -247,14 +247,14 @@ if (ENABLE_CUBEB) target_compile_definitions(audio_core PRIVATE HAVE_CUBEB=1) endif() -if (ENABLE_SDL2) +if (ENABLE_SDL3) target_sources(audio_core PRIVATE sink/sdl2_sink.cpp sink/sdl2_sink.h ) - target_link_libraries(audio_core PRIVATE SDL2::SDL2) - target_compile_definitions(audio_core PRIVATE HAVE_SDL2) + target_link_libraries(audio_core PRIVATE SDL3::SDL3) + target_compile_definitions(audio_core PRIVATE HAVE_SDL3) endif() if(ANDROID) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 25ed58620e..4a9b537116 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "audio_core/common/common.h" #include "audio_core/sink/sdl2_sink.h" diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index d455323e05..05a123fd6e 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -47,7 +47,7 @@ else() ) endif() -if (ENABLE_SDL2) +if (ENABLE_SDL3) target_sources(input_common PRIVATE drivers/joycon.cpp drivers/joycon.h @@ -73,8 +73,8 @@ if (ENABLE_SDL2) helpers/joycon_protocol/rumble.cpp helpers/joycon_protocol/rumble.h ) - target_link_libraries(input_common PRIVATE SDL2::SDL2) - target_compile_definitions(input_common PRIVATE HAVE_SDL2) + target_link_libraries(input_common PRIVATE SDL3::SDL3) + target_compile_definitions(input_common PRIVATE HAVE_SDL3) endif() if (ENABLE_LIBUSB) diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index a140ad072c..58240d327c 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include "common/common_types.h" #include "common/threadsafe_queue.h" diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 00e03bd935..b47cce6137 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -468,9 +468,9 @@ if (YUZU_USE_BUNDLED_QT) copy_yuzu_Qt6_deps(yuzu) endif() -if (ENABLE_SDL2) - target_link_libraries(yuzu PRIVATE SDL2::SDL2) - target_compile_definitions(yuzu PRIVATE HAVE_SDL2) +if (ENABLE_SDL3) + target_link_libraries(yuzu PRIVATE SDL3::SDL3) + target_compile_definitions(yuzu PRIVATE HAVE_SDL3) endif() if (MSVC) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index fc7a953d77..58c1b151e2 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -98,7 +98,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #ifdef HAVE_SDL2 #include #include -#include // For SDL ScreenSaver functions +#include // For SDL ScreenSaver functions #endif #include diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index a60650bc19..47e0f7e5e1 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -41,7 +41,7 @@ target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) -target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2) +target_link_libraries(yuzu-cmd PRIVATE SDL3::SDL3) if(UNIX AND NOT APPLE) install(TARGETS yuzu-cmd) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 4b56f3794b..f0c1100d09 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -3,7 +3,7 @@ // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include +#include #include "common/logging/log.h" #include "common/scm_rev.h" diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 32f365e0d0..15b634bf63 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -9,7 +9,7 @@ #include #define SDL_MAIN_HANDLED -#include +#include #include #include diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index 506137bd8a..e4f01ece24 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -18,7 +18,7 @@ #include #endif -#include +#include EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index f509652bf6..ba4b29e9ae 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -12,7 +12,7 @@ #include "video_core/renderer_vulkan/renderer_vulkan.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" -#include +#include #include EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, diff --git a/src/yuzu_cmd/sdl_config.cpp b/src/yuzu_cmd/sdl_config.cpp index 6e0f254b6b..5d303571b1 100644 --- a/src/yuzu_cmd/sdl_config.cpp +++ b/src/yuzu_cmd/sdl_config.cpp @@ -3,7 +3,7 @@ // SDL will break our main function in yuzu-cmd if we don't define this before adding SDL.h #define SDL_MAIN_HANDLED -#include +#include #include "common/logging/log.h" #include "input_common/main.h" From 0115a5fcc0add3bcd0311a793e492a5149fb0d9d Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 19/30] rename all symbols --- src/audio_core/sink/sdl2_sink.cpp | 4 +- src/input_common/drivers/sdl_driver.cpp | 182 +++++++++--------- src/input_common/drivers/sdl_driver.h | 6 +- src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 42 ++-- .../emu_window/emu_window_sdl2_gl.cpp | 6 +- .../emu_window/emu_window_sdl2_null.cpp | 2 +- .../emu_window/emu_window_sdl2_vk.cpp | 4 +- 7 files changed, 123 insertions(+), 123 deletions(-) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 4a9b537116..72c02058b3 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp @@ -42,7 +42,7 @@ public: SDL_AudioSpec spec; spec.freq = TargetSampleRate; spec.channels = static_cast(device_channels); - spec.format = AUDIO_S16SYS; + spec.format = SDL_AUDIO_S16; spec.samples = TargetSampleCount * 2; spec.callback = &SDLSinkStream::DataCallback; spec.userdata = this; @@ -260,7 +260,7 @@ bool IsSDLSuitable() { SDL_AudioSpec spec; spec.freq = TargetSampleRate; spec.channels = 2u; - spec.format = AUDIO_S16SYS; + spec.format = SDL_AUDIO_S16; spec.samples = TargetSampleCount * 2; spec.callback = nullptr; spec.userdata = nullptr; diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 972abec9fe..100a2516e7 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -15,7 +15,7 @@ namespace InputCommon { namespace { Common::UUID GetGUID(SDL_Joystick* joystick) { - const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); + const SDL_GUID guid = SDL_GetJoystickGUID(joystick); std::array data{}; std::memcpy(data.data(), guid.data, sizeof(data)); // Clear controller name crc @@ -35,9 +35,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) { class SDLJoystick { public: SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, - SDL_GameController* game_controller) - : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, - sdl_controller{game_controller, &SDL_GameControllerClose} { + SDL_Gamepad* game_controller) + : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_CloseJoystick}, + sdl_controller{game_controller, &SDL_CloseGamepad} { EnableMotion(); } @@ -45,18 +45,18 @@ public: if (!sdl_controller) { return; } - SDL_GameController* controller = sdl_controller.get(); + SDL_Gamepad* controller = sdl_controller.get(); if (HasMotion()) { - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_FALSE); - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_FALSE); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, false); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, false); } - has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE; - has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE; + has_accel = SDL_GamepadHasSensor(controller, SDL_SENSOR_ACCEL) == true; + has_gyro = SDL_GamepadHasSensor(controller, SDL_SENSOR_GYRO) == true; if (has_accel) { - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, true); } if (has_gyro) { - SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); + SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, true); } } @@ -64,7 +64,7 @@ public: return has_gyro || has_accel; } - bool UpdateMotion(SDL_ControllerSensorEvent event) { + bool UpdateMotion(SDL_GamepadSensorEvent event) { constexpr float gravity_constant = 9.80665f; std::scoped_lock lock{mutex}; const u64 time_difference = event.timestamp - last_motion_update; @@ -136,11 +136,11 @@ public: f32 high_amplitude = vibration.high_amplitude * high_frequency_scale; if (sdl_controller) { - return SDL_GameControllerRumble(sdl_controller.get(), static_cast(low_amplitude), + return SDL_RumbleGamepad(sdl_controller.get(), static_cast(low_amplitude), static_cast(high_amplitude), rumble_max_duration_ms) != -1; } else if (sdl_joystick) { - return SDL_JoystickRumble(sdl_joystick.get(), static_cast(low_amplitude), + return SDL_RumbleJoystick(sdl_joystick.get(), static_cast(low_amplitude), static_cast(high_amplitude), rumble_max_duration_ms) != -1; } @@ -150,11 +150,11 @@ public: bool HasHDRumble() const { if (sdl_controller) { - const auto type = SDL_GameControllerGetType(sdl_controller.get()); - return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) || - (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || - (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || - (type == SDL_CONTROLLER_TYPE_PS5); + const auto type = SDL_GetGamepadType(sdl_controller.get()); + return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) || + (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || + (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || + (type == SDL_GAMEPAD_TYPE_PS5); } return false; } @@ -201,11 +201,11 @@ public: return sdl_joystick.get(); } - SDL_GameController* GetSDLGameController() const { + SDL_Gamepad* GetSDLGameController() const { return sdl_controller.get(); } - void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) { + void SetSDLJoystick(SDL_Joystick* joystick, SDL_Gamepad* controller) { sdl_joystick.reset(joystick); sdl_controller.reset(controller); } @@ -253,28 +253,28 @@ public: std::string GetControllerName() const { if (sdl_controller) { - switch (SDL_GameControllerGetType(sdl_controller.get())) { - case SDL_CONTROLLER_TYPE_XBOX360: + switch (SDL_GetGamepadType(sdl_controller.get())) { + case SDL_GAMEPAD_TYPE_XBOX360: return "Xbox 360 Controller"; - case SDL_CONTROLLER_TYPE_XBOXONE: + case SDL_GAMEPAD_TYPE_XBOXONE: return "Xbox One Controller"; - case SDL_CONTROLLER_TYPE_PS3: + case SDL_GAMEPAD_TYPE_PS3: return "DualShock 3 Controller"; - case SDL_CONTROLLER_TYPE_PS4: + case SDL_GAMEPAD_TYPE_PS4: return "DualShock 4 Controller"; - case SDL_CONTROLLER_TYPE_PS5: + case SDL_GAMEPAD_TYPE_PS5: return "DualSense Controller"; default: break; } - const auto name = SDL_GameControllerName(sdl_controller.get()); + const auto name = SDL_GetGamepadName(sdl_controller.get()); if (name) { return name; } } if (sdl_joystick) { - const auto name = SDL_JoystickName(sdl_joystick.get()); + const auto name = SDL_GetJoystickName(sdl_joystick.get()); if (name) { return name; } @@ -286,8 +286,8 @@ public: private: Common::UUID guid; int port; - std::unique_ptr sdl_joystick; - std::unique_ptr sdl_controller; + std::unique_ptr sdl_joystick; + std::unique_ptr sdl_controller; mutable std::mutex mutex; u64 last_motion_update{}; @@ -323,7 +323,7 @@ std::shared_ptr SDLDriver::GetSDLJoystickByGUID(const std::string& } std::shared_ptr SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { - auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); + auto sdl_joystick = SDL_GetJoystickFromID(sdl_id); const auto guid = GetGUID(sdl_joystick); std::scoped_lock lock{joystick_map_mutex}; @@ -346,11 +346,11 @@ std::shared_ptr SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl } void SDLDriver::InitJoystick(int joystick_index) { - SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); - SDL_GameController* sdl_gamecontroller = nullptr; + SDL_Joystick* sdl_joystick = SDL_OpenJoystick(joystick_index); + SDL_Gamepad* sdl_gamecontroller = nullptr; - if (SDL_IsGameController(joystick_index)) { - sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); + if (SDL_IsGamepad(joystick_index)) { + sdl_gamecontroller = SDL_OpenGamepad(joystick_index); } if (!sdl_joystick) { @@ -364,7 +364,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) { LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); - SDL_JoystickClose(sdl_joystick); + SDL_CloseJoystick(sdl_joystick); return; } } @@ -372,7 +372,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (Settings::values.enable_procon_driver) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && guid.uuid[8] == 0x09) { LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); - SDL_JoystickClose(sdl_joystick); + SDL_CloseJoystick(sdl_joystick); return; } } @@ -428,35 +428,35 @@ void SDLDriver::PumpEvents() const { void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { switch (event.type) { - case SDL_JOYBUTTONUP: { + case SDL_EVENT_JOYSTICK_BUTTON_UP: { if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetButton(identifier, event.jbutton.button, false); } break; } - case SDL_JOYBUTTONDOWN: { + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: { if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetButton(identifier, event.jbutton.button, true); } break; } - case SDL_JOYHATMOTION: { + case SDL_EVENT_JOYSTICK_HAT_MOTION: { if (const auto joystick = GetSDLJoystickBySDLID(event.jhat.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetHatButton(identifier, event.jhat.hat, event.jhat.value); } break; } - case SDL_JOYAXISMOTION: { + case SDL_EVENT_JOYSTICK_AXIS_MOTION: { if (const auto joystick = GetSDLJoystickBySDLID(event.jaxis.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetAxis(identifier, event.jaxis.axis, event.jaxis.value / 32767.0f); } break; } - case SDL_CONTROLLERSENSORUPDATE: { + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: { if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { if (joystick->UpdateMotion(event.csensor)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); @@ -465,18 +465,18 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { } break; } - case SDL_JOYBATTERYUPDATED: { + case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: { if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level)); } break; } - case SDL_JOYDEVICEREMOVED: + case SDL_EVENT_JOYSTICK_REMOVED: LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); - CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); + CloseJoystick(SDL_GetJoystickFromID(event.jdevice.which)); break; - case SDL_JOYDEVICEADDED: + case SDL_EVENT_JOYSTICK_ADDED: LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which); InitJoystick(event.jdevice.which); break; @@ -502,8 +502,8 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); // Disable hidapi drivers for joycon controllers when the custom joycon driver is enabled @@ -533,8 +533,8 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); // If the frontend is going to manage the event loop, then we don't start one here - start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == 0; - if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { + start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) == 0; + if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { LOG_CRITICAL(Input, "SDL_Init failed with: {}", SDL_GetError()); return; } @@ -561,12 +561,12 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDLDriver::~SDLDriver() { CloseJoysticks(); - SDL_DelEventWatch(&SDLEventWatcher, this); + SDL_RemoveEventWatch(&SDLEventWatcher, this); initialized = false; if (start_thread) { vibration_thread.join(); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD); } } @@ -762,13 +762,13 @@ Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& g Common::ParamPackage SDLDriver::BuildParamPackageForBinding( int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const { switch (binding.bindType) { - case SDL_CONTROLLER_BINDTYPE_NONE: + case SDL_GAMEPAD_BINDTYPE_NONE: break; - case SDL_CONTROLLER_BINDTYPE_AXIS: + case SDL_GAMEPAD_BINDTYPE_AXIS: return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); - case SDL_CONTROLLER_BINDTYPE_BUTTON: + case SDL_GAMEPAD_BINDTYPE_BUTTON: return BuildButtonParamPackageForButton(port, guid, binding.value.button); - case SDL_CONTROLLER_BINDTYPE_HAT: + case SDL_GAMEPAD_BINDTYPE_HAT: return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat, static_cast(binding.value.hat.hat_mask)); } @@ -810,8 +810,8 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p // Add the missing bindings for ZL/ZR static constexpr ZButtonBindings switch_to_sdl_axis{{ - {Settings::NativeButton::ZL, SDL_CONTROLLER_AXIS_TRIGGERLEFT}, - {Settings::NativeButton::ZR, SDL_CONTROLLER_AXIS_TRIGGERRIGHT}, + {Settings::NativeButton::ZL, SDL_GAMEPAD_AXIS_LEFT_TRIGGER}, + {Settings::NativeButton::ZR, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER}, }}; // Parameters contain two joysticks return dual @@ -830,41 +830,41 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p ButtonBindings SDLDriver::GetDefaultButtonBinding( const std::shared_ptr& joystick) const { // Default SL/SR mapping for other controllers - auto sll_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; - auto srl_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; - auto slr_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; - auto srr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; + auto sll_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; + auto srl_button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; + auto slr_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; + auto srr_button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; if (joystick->IsJoyconLeft()) { - sll_button = SDL_CONTROLLER_BUTTON_PADDLE2; - srl_button = SDL_CONTROLLER_BUTTON_PADDLE4; + sll_button = SDL_GAMEPAD_BUTTON_LEFT_PADDLE1; + srl_button = SDL_GAMEPAD_BUTTON_LEFT_PADDLE2; } if (joystick->IsJoyconRight()) { - slr_button = SDL_CONTROLLER_BUTTON_PADDLE3; - srr_button = SDL_CONTROLLER_BUTTON_PADDLE1; + slr_button = SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2; + srr_button = SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1; } return { - std::pair{Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, - {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, - {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, - {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, - {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, - {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, - {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, - {Settings::NativeButton::R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, - {Settings::NativeButton::Plus, SDL_CONTROLLER_BUTTON_START}, - {Settings::NativeButton::Minus, SDL_CONTROLLER_BUTTON_BACK}, - {Settings::NativeButton::DLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT}, - {Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP}, - {Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, - {Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN}, + std::pair{Settings::NativeButton::A, SDL_GAMEPAD_BUTTON_EAST}, + {Settings::NativeButton::B, SDL_GAMEPAD_BUTTON_SOUTH}, + {Settings::NativeButton::X, SDL_GAMEPAD_BUTTON_NORTH}, + {Settings::NativeButton::Y, SDL_GAMEPAD_BUTTON_WEST}, + {Settings::NativeButton::LStick, SDL_GAMEPAD_BUTTON_LEFT_STICK}, + {Settings::NativeButton::RStick, SDL_GAMEPAD_BUTTON_RIGHT_STICK}, + {Settings::NativeButton::L, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {Settings::NativeButton::R, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, + {Settings::NativeButton::Plus, SDL_GAMEPAD_BUTTON_START}, + {Settings::NativeButton::Minus, SDL_GAMEPAD_BUTTON_BACK}, + {Settings::NativeButton::DLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT}, + {Settings::NativeButton::DUp, SDL_GAMEPAD_BUTTON_DPAD_UP}, + {Settings::NativeButton::DRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, + {Settings::NativeButton::DDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN}, {Settings::NativeButton::SLLeft, sll_button}, {Settings::NativeButton::SRLeft, srl_button}, {Settings::NativeButton::SLRight, slr_button}, {Settings::NativeButton::SRRight, srr_button}, - {Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE}, - {Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1}, + {Settings::NativeButton::Home, SDL_GAMEPAD_BUTTON_GUIDE}, + {Settings::NativeButton::Screenshot, SDL_GAMEPAD_BUTTON_MISC1}, }; } @@ -960,9 +960,9 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p AnalogMapping mapping = {}; const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); if (params.Has("guid2")) { const auto identifier = joystick2->GetPadIdentifier(); PreSetController(identifier); @@ -987,9 +987,9 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p left_offset_x, left_offset_y)); } const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); const auto identifier = joystick->GetPadIdentifier(); PreSetController(identifier); PreSetAxis(identifier, binding_right_x.value.axis); @@ -1105,13 +1105,13 @@ bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) { const auto& axis_x = params.Get("axis_x", 0); const auto& axis_y = params.Get("axis_y", 0); const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY); + SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) { return false; diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 58240d327c..bdd2476cb0 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -15,7 +15,7 @@ #include "input_common/input_engine.h" union SDL_Event; -using SDL_GameController = struct _SDL_GameController; +using SDL_Gamepad = struct _SDL_GameController; using SDL_Joystick = struct _SDL_Joystick; using SDL_JoystickID = s32; @@ -24,9 +24,9 @@ namespace InputCommon { class SDLJoystick; using ButtonBindings = - std::array, 20>; + std::array, 20>; using ZButtonBindings = - std::array, 2>; + std::array, 2>; class SDLDriver : public InputEngine { public: diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index f0c1100d09..cb3e4bc576 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -21,7 +21,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) : input_subsystem{input_subsystem_}, system{system_} { input_subsystem->Initialize(); - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}, Exiting...", SDL_GetError()); exit(1); } @@ -176,50 +176,50 @@ void EmuWindow_SDL2::WaitEvent() { switch (event.type) { case SDL_WINDOWEVENT: switch (event.window.event) { - case SDL_WINDOWEVENT_SIZE_CHANGED: - case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_MAXIMIZED: - case SDL_WINDOWEVENT_RESTORED: + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_MAXIMIZED: + case SDL_EVENT_WINDOW_RESTORED: OnResize(); break; - case SDL_WINDOWEVENT_MINIMIZED: - case SDL_WINDOWEVENT_EXPOSED: - is_shown = event.window.event == SDL_WINDOWEVENT_EXPOSED; + case SDL_EVENT_WINDOW_MINIMIZED: + case SDL_EVENT_WINDOW_EXPOSED: + is_shown = event.window.event == SDL_EVENT_WINDOW_EXPOSED; OnResize(); break; - case SDL_WINDOWEVENT_CLOSE: + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: is_open = false; break; } break; - case SDL_KEYDOWN: - case SDL_KEYUP: + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: OnKeyEvent(static_cast(event.key.keysym.scancode), event.key.state); break; - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: // ignore if it came from touch if (event.button.which != SDL_TOUCH_MOUSEID) OnMouseMotion(event.motion.x, event.motion.y); break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: // ignore if it came from touch if (event.button.which != SDL_TOUCH_MOUSEID) { OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); } break; - case SDL_FINGERDOWN: + case SDL_EVENT_FINGER_DOWN: OnFingerDown(event.tfinger.x, event.tfinger.y, static_cast(event.tfinger.touchId)); break; - case SDL_FINGERMOTION: + case SDL_EVENT_FINGER_MOTION: OnFingerMotion(event.tfinger.x, event.tfinger.y, static_cast(event.tfinger.touchId)); break; - case SDL_FINGERUP: + case SDL_EVENT_FINGER_UP: OnFingerUp(); break; - case SDL_QUIT: + case SDL_EVENT_QUIT: is_open = false; break; default: @@ -242,19 +242,19 @@ void EmuWindow_SDL2::WaitEvent() { // Credits to Samantas5855 and others for this function. void EmuWindow_SDL2::SetWindowIcon() { - SDL_RWops* const yuzu_icon_stream = SDL_RWFromConstMem((void*)yuzu_icon, yuzu_icon_size); + SDL_IOStream* const yuzu_icon_stream = SDL_IOFromConstMem((void*)yuzu_icon, yuzu_icon_size); if (yuzu_icon_stream == nullptr) { LOG_WARNING(Frontend, "Failed to create Eden icon stream."); return; } - SDL_Surface* const window_icon = SDL_LoadBMP_RW(yuzu_icon_stream, 1); + SDL_Surface* const window_icon = SDL_LoadBMP_IO(yuzu_icon_stream, 1); if (window_icon == nullptr) { LOG_WARNING(Frontend, "Failed to read BMP from stream."); return; } // The icon is attached to the window pointer SDL_SetWindowIcon(render_window, window_icon); - SDL_FreeSurface(window_icon); + SDL_DestroySurface(window_icon); } void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair minimal_size) { diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 15b634bf63..e08e843673 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -30,7 +30,7 @@ public: ~SDLGLContext() { DoneCurrent(); - SDL_GL_DeleteContext(context); + SDL_GL_DestroyContext(context); } void SwapBuffers() override { @@ -100,7 +100,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste SDL_WINDOWPOS_UNDEFINED, // x position SDL_WINDOWPOS_UNDEFINED, // y position Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); if (render_window == nullptr) { LOG_CRITICAL(Frontend, "Failed to create SDL2 window! {}", SDL_GetError()); @@ -148,7 +148,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste EmuWindow_SDL2_GL::~EmuWindow_SDL2_GL() { core_context.reset(); - SDL_GL_DeleteContext(window_context); + SDL_GL_DestroyContext(window_context); } std::unique_ptr EmuWindow_SDL2_GL::CreateSharedContext() const { diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index e4f01ece24..0eaecc6085 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -28,7 +28,7 @@ EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subs render_window = SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SetWindowIcon(); diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index ba4b29e9ae..dfac272342 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -25,11 +25,11 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste render_window = SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SDL_SysWMinfo wm; SDL_VERSION(&wm.version); - if (SDL_GetWindowWMInfo(render_window, &wm) == SDL_FALSE) { + if (SDL_GetWindowWMInfo(render_window, &wm) == false) { LOG_CRITICAL(Frontend, "Failed to get information from the window manager: {}", SDL_GetError()); std::exit(EXIT_FAILURE); From 6f0255a8c4139c8380fbd75c9933083546393408 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 20/30] rename some headers --- src/input_common/drivers/joycon.h | 2 +- src/input_common/helpers/joycon_protocol/joycon_types.h | 2 +- src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp | 2 +- src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h index 112e970e15..92ebf0c813 100644 --- a/src/input_common/drivers/joycon.h +++ b/src/input_common/drivers/joycon.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "input_common/input_engine.h" diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index 792f124e14..439becb2ed 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include "common/bit_field.h" #include "common/common_funcs.h" diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index 0eaecc6085..cd1003a10e 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -15,7 +15,7 @@ #ifdef YUZU_USE_EXTERNAL_SDL2 // Include this before SDL.h to prevent the external from including a dummy #define USING_GENERATED_CONFIG_H -#include +#include #endif #include diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index dfac272342..3b3382556b 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -13,7 +13,7 @@ #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" #include -#include +#include EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) From 33db18a6bee67b26fef3ef2bbf603478bb2bfa1f Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 21/30] new audio api changes --- src/audio_core/sink/sdl2_sink.cpp | 190 +++++++++++++++--------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 72c02058b3..2d07a35c43 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp @@ -4,6 +4,7 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include @@ -13,7 +14,6 @@ #include "audio_core/sink/sdl2_sink.h" #include "audio_core/sink/sink_stream.h" #include "common/logging/log.h" -#include "common/scope_exit.h" #include "core/core.h" namespace AudioCore::Sink { @@ -39,37 +39,53 @@ public: system_channels = system_channels_; device_channels = device_channels_; - SDL_AudioSpec spec; + SDL_AudioSpec spec{}; spec.freq = TargetSampleRate; - spec.channels = static_cast(device_channels); + spec.channels = static_cast(device_channels); spec.format = SDL_AUDIO_S16; - spec.samples = TargetSampleCount * 2; - spec.callback = &SDLSinkStream::DataCallback; - spec.userdata = this; + SDL_AudioDeviceID device_id = 0; std::string device_name{output_device}; - bool capture{false}; + bool is_capture{false}; + if (type == StreamType::In) { device_name = input_device; - capture = true; + is_capture = true; } - SDL_AudioSpec obtained; - if (device_name.empty()) { - device = SDL_OpenAudioDevice(nullptr, capture, &spec, &obtained, false); - } else { - device = SDL_OpenAudioDevice(device_name.c_str(), capture, &spec, &obtained, false); + if (!device_name.empty()) { + int count = 0; + SDL_AudioDeviceID* devices = is_capture ? SDL_GetAudioRecordingDevices(&count) + : SDL_GetAudioPlaybackDevices(&count); + + if (devices) { + for (int i = 0; i < count; ++i) { + const char* name = SDL_GetAudioDeviceName(devices[i]); + if (name && device_name == name) { + device_id = devices[i]; + break; + } + } + SDL_free(devices); + } } - if (device == 0) { - LOG_CRITICAL(Audio_Sink, "Error opening SDL audio device: {}", SDL_GetError()); + if (device_id == 0) { + device_id = + is_capture ? SDL_AUDIO_DEVICE_DEFAULT_RECORDING : SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; + } + + stream = SDL_OpenAudioDeviceStream( + device_id, &spec, + is_capture ? &SDLSinkStream::CaptureCallback : &SDLSinkStream::PlaybackCallback, this); + + if (!stream) { + LOG_CRITICAL(Audio_Sink, "Error opening SDL audio stream: {}", SDL_GetError()); return; } - LOG_INFO(Service_Audio, - "Opening SDL stream {} with: rate {} channels {} (system channels {}) " - " samples {}", - device, obtained.freq, obtained.channels, system_channels, obtained.samples); + LOG_INFO(Service_Audio, "Opening SDL stream with: rate {} channels {} (system channels {})", + spec.freq, spec.channels, system_channels); } /** @@ -84,13 +100,14 @@ public: * Finalize the sink stream. */ void Finalize() override { - if (device == 0) { + if (!stream) { return; } Stop(); - SDL_ClearQueuedAudio(device); - SDL_CloseAudioDevice(device); + SDL_ClearAudioStream(stream); + SDL_DestroyAudioStream(stream); + stream = nullptr; } /** @@ -100,62 +117,80 @@ public: * Default false. */ void Start(bool resume = false) override { - if (device == 0 || !paused) { + if (!stream || !paused) { return; } paused = false; - SDL_PauseAudioDevice(device, 0); + SDL_ResumeAudioStreamDevice(stream); } /** * Stop the sink stream. */ void Stop() override { - if (device == 0 || paused) { + if (!stream || paused) { return; } SignalPause(); - SDL_PauseAudioDevice(device, 1); + SDL_PauseAudioStreamDevice(stream); + paused = true; } private: - /** - * Main callback from SDL. Either expects samples from us (audio render/audio out), or will - * provide samples to be copied (audio in). - * - * @param userdata - Custom data pointer passed along, points to a SDLSinkStream. - * @param stream - Buffer of samples to be filled or read. - * @param len - Length of the stream in bytes. - */ - static void DataCallback(void* userdata, Uint8* stream, int len) { + static void PlaybackCallback(void* userdata, SDL_AudioStream* stream, int additional_amount, + int total_amount) { auto* impl = static_cast(userdata); - if (!impl) { return; } const std::size_t num_channels = impl->GetDeviceChannels(); const std::size_t frame_size = num_channels; - const std::size_t num_frames{len / num_channels / sizeof(s16)}; + const std::size_t num_frames = additional_amount / (sizeof(s16) * frame_size); - if (impl->type == StreamType::In) { - std::span input_buffer{reinterpret_cast(stream), - num_frames * frame_size}; - impl->ProcessAudioIn(input_buffer, num_frames); - } else { - std::span output_buffer{reinterpret_cast(stream), num_frames * frame_size}; - impl->ProcessAudioOutAndRender(output_buffer, num_frames); + if (num_frames == 0) { + return; + } + + std::vector buffer(num_frames * frame_size); + impl->ProcessAudioOutAndRender(buffer, num_frames); + SDL_PutAudioStreamData(stream, buffer.data(), + static_cast(buffer.size() * sizeof(s16))); + } + + static void CaptureCallback(void* userdata, SDL_AudioStream* stream, int additional_amount, + int total_amount) { + auto* impl = static_cast(userdata); + if (!impl) { + return; + } + + const std::size_t num_channels = impl->GetDeviceChannels(); + const std::size_t frame_size = num_channels; + const std::size_t bytes_available = SDL_GetAudioStreamAvailable(stream); + + if (bytes_available == 0) { + return; + } + + const std::size_t num_frames = bytes_available / (sizeof(s16) * frame_size); + std::vector buffer(num_frames * frame_size); + + int bytes_read = + SDL_GetAudioStreamData(stream, buffer.data(), static_cast(bytes_available)); + if (bytes_read > 0) { + const std::size_t frames_read = bytes_read / (sizeof(s16) * frame_size); + impl->ProcessAudioIn(buffer, frames_read); } } - /// SDL device id of the opened input/output device - SDL_AudioDeviceID device{}; + SDL_AudioStream* stream{nullptr}; }; SDLSink::SDLSink(std::string_view target_device_name) { if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) { LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError()); return; } @@ -218,66 +253,31 @@ std::vector ListSDLSinkDevices(bool capture) { std::vector device_list; if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) { LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError()); return {}; } } - const int device_count = SDL_GetNumAudioDevices(capture); - for (int i = 0; i < device_count; ++i) { - if (const char* name = SDL_GetAudioDeviceName(i, capture)) { - device_list.emplace_back(name); + int count = 0; + SDL_AudioDeviceID* devices = + capture ? SDL_GetAudioRecordingDevices(&count) : SDL_GetAudioPlaybackDevices(&count); + + if (devices) { + for (int i = 0; i < count; ++i) { + const char* name = SDL_GetAudioDeviceName(devices[i]); + if (name) { + device_list.emplace_back(name); + } } + SDL_free(devices); } return device_list; } -/* REVERSION to 3833 - function GetSDLLatency() REINTRODUCED FROM 3833 - DIABLO 3 FIX */ u32 GetSDLLatency() { return TargetSampleCount * 2; } -// REVERTED back to 3833 - Below function IsSDLSuitable() removed, reverting to GetSDLLatency() above. - DIABLO 3 FIX -/* -bool IsSDLSuitable() { -#if !defined(HAVE_SDL2) - return false; -#else - // Check SDL can init - if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { - LOG_ERROR(Audio_Sink, "SDL failed to init, it is not suitable. Error: {}", - SDL_GetError()); - return false; - } - } - - // We can set any latency frequency we want with SDL, so no need to check that. - - // Check we can open a device with standard parameters - SDL_AudioSpec spec; - spec.freq = TargetSampleRate; - spec.channels = 2u; - spec.format = SDL_AUDIO_S16; - spec.samples = TargetSampleCount * 2; - spec.callback = nullptr; - spec.userdata = nullptr; - - SDL_AudioSpec obtained; - auto device = SDL_OpenAudioDevice(nullptr, false, &spec, &obtained, false); - - if (device == 0) { - LOG_ERROR(Audio_Sink, "SDL failed to open a device, it is not suitable. Error: {}", - SDL_GetError()); - return false; - } - - SDL_CloseAudioDevice(device); - return true; -#endif -} -*/ - -} // namespace AudioCore::Sink +} // namespace AudioCore::Sink \ No newline at end of file From e9ebdf02f434f110d96980a06a82c1067669fd8f Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 22/30] gamepad and joystick apis --- src/input_common/drivers/sdl_driver.cpp | 349 ++++++++++++------------ src/input_common/drivers/sdl_driver.h | 50 +--- 2 files changed, 179 insertions(+), 220 deletions(-) diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 100a2516e7..d140b00ca0 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -8,7 +8,7 @@ #include "common/param_package.h" #include "common/settings.h" #include "common/thread.h" -#include "common/vector_math.h" +// #include "common/vector_math.h" // Not used directly #include "input_common/drivers/sdl_driver.h" namespace InputCommon { @@ -18,45 +18,41 @@ Common::UUID GetGUID(SDL_Joystick* joystick) { const SDL_GUID guid = SDL_GetJoystickGUID(joystick); std::array data{}; std::memcpy(data.data(), guid.data, sizeof(data)); - // Clear controller name crc std::memset(data.data() + 2, 0, sizeof(u16)); return Common::UUID{data}; } } // Anonymous namespace -static int SDLEventWatcher(void* user_data, SDL_Event* event) { +static bool SDLEventWatcher(void* user_data, SDL_Event* event) { auto* const sdl_state = static_cast(user_data); - sdl_state->HandleGameControllerEvent(*event); - - return 0; + return false; } class SDLJoystick { public: - SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, - SDL_Gamepad* game_controller) + SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick, SDL_Gamepad* gamepad) : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_CloseJoystick}, - sdl_controller{game_controller, &SDL_CloseGamepad} { + sdl_gamepad{gamepad, &SDL_CloseGamepad} { EnableMotion(); } void EnableMotion() { - if (!sdl_controller) { + if (!sdl_gamepad) { return; } - SDL_Gamepad* controller = sdl_controller.get(); + SDL_Gamepad* gamepad = sdl_gamepad.get(); if (HasMotion()) { - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, false); - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, false); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_ACCEL, false); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, false); } - has_accel = SDL_GamepadHasSensor(controller, SDL_SENSOR_ACCEL) == true; - has_gyro = SDL_GamepadHasSensor(controller, SDL_SENSOR_GYRO) == true; + has_accel = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_ACCEL); + has_gyro = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_GYRO); if (has_accel) { - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_ACCEL, true); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_ACCEL, true); } if (has_gyro) { - SDL_SetGamepadSensorEnabled(controller, SDL_SENSOR_GYRO, true); + SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, true); } } @@ -84,25 +80,22 @@ public: } } - // Ignore duplicated timestamps if (time_difference == 0) { return false; } - // Motion data is invalid if (motion.accel_x == 0 && motion.gyro_x == 0 && motion.accel_y == 0 && motion.gyro_y == 0 && motion.accel_z == 0 && motion.gyro_z == 0) { if (motion_error_count++ < 200) { return false; } - // Try restarting the sensor motion_error_count = 0; EnableMotion(); return false; } motion_error_count = 0; - motion.delta_timestamp = time_difference * 1000; + motion.delta_timestamp = time_difference; return true; } @@ -116,13 +109,13 @@ public: constexpr f32 low_width_sensitivity_limit = 400.0f; constexpr f32 high_start_sensitivity_limit = 200.0f; constexpr f32 high_width_sensitivity_limit = 700.0f; - // Try to provide some feeling of the frequency by reducing the amplitude depending on it. + f32 low_frequency_scale = 1.0f; if (vibration.low_frequency > low_start_sensitivity_limit) { low_frequency_scale = (std::max)(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) / - low_width_sensitivity_limit, - 0.3f); + low_width_sensitivity_limit, + 0.3f); } f32 low_amplitude = vibration.low_amplitude * low_frequency_scale; @@ -130,27 +123,25 @@ public: if (vibration.high_frequency > high_start_sensitivity_limit) { high_frequency_scale = (std::max)(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) / - high_width_sensitivity_limit, - 0.3f); + high_width_sensitivity_limit, + 0.3f); } f32 high_amplitude = vibration.high_amplitude * high_frequency_scale; - if (sdl_controller) { - return SDL_RumbleGamepad(sdl_controller.get(), static_cast(low_amplitude), - static_cast(high_amplitude), - rumble_max_duration_ms) != -1; + if (sdl_gamepad) { + return SDL_RumbleGamepad(sdl_gamepad.get(), static_cast(low_amplitude), + static_cast(high_amplitude), rumble_max_duration_ms); } else if (sdl_joystick) { return SDL_RumbleJoystick(sdl_joystick.get(), static_cast(low_amplitude), - static_cast(high_amplitude), - rumble_max_duration_ms) != -1; + static_cast(high_amplitude), rumble_max_duration_ms); } return false; } bool HasHDRumble() const { - if (sdl_controller) { - const auto type = SDL_GetGamepadType(sdl_controller.get()); + if (sdl_gamepad) { + const auto type = SDL_GetGamepadType(sdl_gamepad.get()); return (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO) || (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || (type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || @@ -172,9 +163,6 @@ public: return is_vibration_tested; } - /** - * The Pad identifier of the joystick - */ const PadIdentifier GetPadIdentifier() const { return { .guid = guid, @@ -183,16 +171,10 @@ public: }; } - /** - * The guid of the joystick - */ const Common::UUID& GetGUID() const { return guid; } - /** - * The number of joystick from the same type that were connected before this joystick - */ int GetPort() const { return port; } @@ -201,13 +183,13 @@ public: return sdl_joystick.get(); } - SDL_Gamepad* GetSDLGameController() const { - return sdl_controller.get(); + SDL_Gamepad* GetSDLGamepad() const { + return sdl_gamepad.get(); } - void SetSDLJoystick(SDL_Joystick* joystick, SDL_Gamepad* controller) { + void SetSDLJoystick(SDL_Joystick* joystick, SDL_Gamepad* gamepad) { sdl_joystick.reset(joystick); - sdl_controller.reset(controller); + sdl_gamepad.reset(gamepad); } bool IsJoyconLeft() const { @@ -232,28 +214,27 @@ public: return false; } - Common::Input::BatteryLevel GetBatteryLevel(SDL_JoystickPowerLevel battery_level) { + Common::Input::BatteryLevel GetBatteryLevel(SDL_PowerState battery_level) { switch (battery_level) { - case SDL_JOYSTICK_POWER_EMPTY: - return Common::Input::BatteryLevel::Empty; - case SDL_JOYSTICK_POWER_LOW: + case SDL_POWERSTATE_ERROR: + case SDL_POWERSTATE_UNKNOWN: + return Common::Input::BatteryLevel::None; + case SDL_POWERSTATE_ON_BATTERY: return Common::Input::BatteryLevel::Low; - case SDL_JOYSTICK_POWER_MEDIUM: - return Common::Input::BatteryLevel::Medium; - case SDL_JOYSTICK_POWER_FULL: - case SDL_JOYSTICK_POWER_MAX: - return Common::Input::BatteryLevel::Full; - case SDL_JOYSTICK_POWER_WIRED: + case SDL_POWERSTATE_NO_BATTERY: + return Common::Input::BatteryLevel::None; + case SDL_POWERSTATE_CHARGING: return Common::Input::BatteryLevel::Charging; - case SDL_JOYSTICK_POWER_UNKNOWN: + case SDL_POWERSTATE_CHARGED: + return Common::Input::BatteryLevel::Full; default: return Common::Input::BatteryLevel::None; } } std::string GetControllerName() const { - if (sdl_controller) { - switch (SDL_GetGamepadType(sdl_controller.get())) { + if (sdl_gamepad) { + switch (SDL_GetGamepadType(sdl_gamepad.get())) { case SDL_GAMEPAD_TYPE_XBOX360: return "Xbox 360 Controller"; case SDL_GAMEPAD_TYPE_XBOXONE: @@ -267,7 +248,7 @@ public: default: break; } - const auto name = SDL_GetGamepadName(sdl_controller.get()); + const auto name = SDL_GetGamepadName(sdl_gamepad.get()); if (name) { return name; } @@ -287,7 +268,7 @@ private: Common::UUID guid; int port; std::unique_ptr sdl_joystick; - std::unique_ptr sdl_controller; + std::unique_ptr sdl_gamepad; mutable std::mutex mutex; u64 last_motion_update{}; @@ -345,16 +326,16 @@ std::shared_ptr SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl return *vec_it; } -void SDLDriver::InitJoystick(int joystick_index) { - SDL_Joystick* sdl_joystick = SDL_OpenJoystick(joystick_index); - SDL_Gamepad* sdl_gamecontroller = nullptr; +void SDLDriver::InitJoystick(SDL_JoystickID joystick_id) { + SDL_Joystick* sdl_joystick = SDL_OpenJoystick(joystick_id); + SDL_Gamepad* sdl_gamepad = nullptr; - if (SDL_IsGamepad(joystick_index)) { - sdl_gamecontroller = SDL_OpenGamepad(joystick_index); + if (SDL_IsGamepad(joystick_id)) { + sdl_gamepad = SDL_OpenGamepad(joystick_id); } if (!sdl_joystick) { - LOG_ERROR(Input, "Failed to open joystick {}", joystick_index); + LOG_ERROR(Input, "Failed to open joystick {}", joystick_id); return; } @@ -363,7 +344,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (Settings::values.enable_joycon_driver) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && (guid.uuid[8] == 0x06 || guid.uuid[8] == 0x07)) { - LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); + LOG_WARNING(Input, "Preferring joycon driver for device ID {}", joystick_id); SDL_CloseJoystick(sdl_joystick); return; } @@ -371,7 +352,7 @@ void SDLDriver::InitJoystick(int joystick_index) { if (Settings::values.enable_procon_driver) { if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && guid.uuid[8] == 0x09) { - LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index); + LOG_WARNING(Input, "Preferring joycon driver for device ID {}", joystick_id); SDL_CloseJoystick(sdl_joystick); return; } @@ -379,7 +360,7 @@ void SDLDriver::InitJoystick(int joystick_index) { std::scoped_lock lock{joystick_map_mutex}; if (joystick_map.find(guid) == joystick_map.end()) { - auto joystick = std::make_shared(guid, 0, sdl_joystick, sdl_gamecontroller); + auto joystick = std::make_shared(guid, 0, sdl_joystick, sdl_gamepad); PreSetController(joystick->GetPadIdentifier()); joystick->EnableMotion(); joystick_map[guid].emplace_back(std::move(joystick)); @@ -392,13 +373,13 @@ void SDLDriver::InitJoystick(int joystick_index) { [](const auto& joystick) { return !joystick->GetSDLJoystick(); }); if (joystick_it != joystick_guid_list.end()) { - (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); + (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamepad); (*joystick_it)->EnableMotion(); return; } const int port = static_cast(joystick_guid_list.size()); - auto joystick = std::make_shared(guid, port, sdl_joystick, sdl_gamecontroller); + auto joystick = std::make_shared(guid, port, sdl_joystick, sdl_gamepad); PreSetController(joystick->GetPadIdentifier()); joystick->EnableMotion(); joystick_guid_list.emplace_back(std::move(joystick)); @@ -408,7 +389,6 @@ void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { const auto guid = GetGUID(sdl_joystick); std::scoped_lock lock{joystick_map_mutex}; - // This call to guid is safe since the joystick is guaranteed to be in the map const auto& joystick_guid_list = joystick_map[guid]; const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), [&sdl_joystick](const auto& joystick) { @@ -457,8 +437,8 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { break; } case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: { - if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { - if (joystick->UpdateMotion(event.csensor)) { + if (auto joystick = GetSDLJoystickBySDLID(event.gsensor.which)) { + if (joystick->UpdateMotion(event.gsensor)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetMotion(identifier, 0, joystick->GetMotion()); } @@ -468,7 +448,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: { if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); - SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level)); + SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.state)); } break; } @@ -477,7 +457,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { CloseJoystick(SDL_GetJoystickFromID(event.jdevice.which)); break; case SDL_EVENT_JOYSTICK_ADDED: - LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which); + LOG_DEBUG(Input, "Controller connected with device ID {}", event.jdevice.which); InitJoystick(event.jdevice.which); break; } @@ -489,24 +469,17 @@ void SDLDriver::CloseJoysticks() { } SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) { - // Set our application name. Currently passed to DBus by SDL and visible to the user through - // their desktop environment. SDL_SetHint(SDL_HINT_APP_NAME, "Eden"); if (!Settings::values.enable_raw_input) { - // Disable raw input. When enabled this setting causes SDL to die when a web applet opens SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); } - // Prevent SDL from adding undesired axis - SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); - - // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers - SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); + // SDL_HINT_ACCELEROMETER_AS_JOYSTICK was removed in SDL3 + // SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE and SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE were removed in + // SDL3 These are now handled by SDL_HINT_JOYSTICK_ENHANCED_REPORTS SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - // Disable hidapi drivers for joycon controllers when the custom joycon driver is enabled if (Settings::values.enable_joycon_driver) { SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0"); } else { @@ -516,7 +489,6 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, "1"); } - // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled if (Settings::values.enable_procon_driver) { SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0"); } else { @@ -525,16 +497,11 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en } SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, "1"); - // Share the same button mapping with non-Nintendo controllers - SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); - - // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native - // driver on Linux. + // SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS was removed in SDL3 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); - // If the frontend is going to manage the event loop, then we don't start one here - start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) == 0; - if (start_thread && SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { + start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD); + if (start_thread && !SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD)) { LOG_CRITICAL(Input, "SDL_Init failed with: {}", SDL_GetError()); return; } @@ -552,10 +519,14 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en } }); } - // Because the events for joystick connection happens before we have our event watcher added, we - // can just open all the joysticks right here - for (int i = 0; i < SDL_NumJoysticks(); ++i) { - InitJoystick(i); + + int num_joysticks; + SDL_JoystickID* joysticks = SDL_GetJoysticks(&num_joysticks); + if (joysticks) { + for (int i = 0; i < num_joysticks; ++i) { + InitJoystick(joysticks[i]); + } + SDL_free(joysticks); } } @@ -592,7 +563,6 @@ std::vector SDLDriver::GetInputDevices() const { } } - // Add dual controllers for (const auto& [key, value] : joystick_map) { for (const auto& joystick : value) { if (joystick->IsJoyconRight()) { @@ -624,15 +594,12 @@ Common::Input::DriverResult SDLDriver::SetVibration( return (amplitude + std::pow(amplitude, factor)) * 0.5f * 0xFFFF; }; - // Default exponential curve for rumble f32 factor = 0.35f; - // If vibration is set as a linear output use a flatter value if (vibration.type == Common::Input::VibrationAmplificationType::Linear) { factor = 0.5f; } - // Amplitude for HD rumble needs no modification if (joystick->HasHDRumble()) { factor = 1.0f; } @@ -677,10 +644,7 @@ bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) { return joystick->HasVibration(); } - // First vibration might fail joystick->RumblePlay(test_vibration); - - // Wait for about 15ms to ensure the controller is ready for the stop command std::this_thread::sleep_for(std::chrono::milliseconds(15)); if (!joystick->RumblePlay(zero_vibration)) { @@ -760,17 +724,17 @@ Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& g } Common::ParamPackage SDLDriver::BuildParamPackageForBinding( - int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const { - switch (binding.bindType) { + int port, const Common::UUID& guid, const SDL_GamepadBinding& binding) const { + switch (binding.input_type) { case SDL_GAMEPAD_BINDTYPE_NONE: break; case SDL_GAMEPAD_BINDTYPE_AXIS: - return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); + return BuildAnalogParamPackageForButton(port, guid, binding.input.axis.axis); case SDL_GAMEPAD_BINDTYPE_BUTTON: - return BuildButtonParamPackageForButton(port, guid, binding.value.button); + return BuildButtonParamPackageForButton(port, guid, binding.input.button); case SDL_GAMEPAD_BINDTYPE_HAT: - return BuildHatParamPackageForButton(port, guid, binding.value.hat.hat, - static_cast(binding.value.hat.hat_mask)); + return BuildHatParamPackageForButton(port, guid, binding.input.hat.hat, + static_cast(binding.input.hat.hat_mask)); } return {}; } @@ -797,28 +761,23 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p } const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return {}; } - // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. - // We will add those afterwards ButtonBindings switch_to_sdl_button; - switch_to_sdl_button = GetDefaultButtonBinding(joystick); - // Add the missing bindings for ZL/ZR static constexpr ZButtonBindings switch_to_sdl_axis{{ {Settings::NativeButton::ZL, SDL_GAMEPAD_AXIS_LEFT_TRIGGER}, {Settings::NativeButton::ZR, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER}, }}; - // Parameters contain two joysticks return dual if (params.Has("guid2")) { const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); - if (joystick2->GetSDLGameController() != nullptr) { + if (joystick2->GetSDLGamepad() != nullptr) { return GetDualControllerMapping(joystick, joystick2, switch_to_sdl_button, switch_to_sdl_axis); } @@ -829,7 +788,6 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p ButtonBindings SDLDriver::GetDefaultButtonBinding( const std::shared_ptr& joystick) const { - // Default SL/SR mapping for other controllers auto sll_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; auto srl_button = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; auto slr_button = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; @@ -873,16 +831,25 @@ ButtonMapping SDLDriver::GetSingleControllerMapping( const ZButtonBindings& switch_to_sdl_axis) const { ButtonMapping mapping; mapping.reserve(switch_to_sdl_button.size() + switch_to_sdl_axis.size()); - auto* controller = joystick->GetSDLGameController(); for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { - const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); + // SDL_GetGamepadBindForButton was removed in SDL3 + // We need to use SDL_GetGamepadStringForButton or work with joystick directly + // For now, create a dummy binding + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; + binding.input.button = sdl_button; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); } for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { - const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); + // SDL_GetGamepadBindForAxis was removed in SDL3 + // We need to use SDL_GetGamepadStringForAxis or work with joystick directly + // For now, create a dummy binding + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding.input.axis.axis = sdl_axis; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); @@ -897,31 +864,41 @@ ButtonMapping SDLDriver::GetDualControllerMapping(const std::shared_ptrGetSDLGameController(); - auto* controller2 = joystick2->GetSDLGameController(); for (const auto& [switch_button, sdl_button] : switch_to_sdl_button) { if (IsButtonOnLeftSide(switch_button)) { - const auto& binding = SDL_GameControllerGetBindForButton(controller2, sdl_button); + // SDL_GetGamepadBindForButton was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; + binding.input.button = sdl_button; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding)); continue; } - const auto& binding = SDL_GameControllerGetBindForButton(controller, sdl_button); + // SDL_GetGamepadBindForButton was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; + binding.input.button = sdl_button; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); } for (const auto& [switch_button, sdl_axis] : switch_to_sdl_axis) { if (IsButtonOnLeftSide(switch_button)) { - const auto& binding = SDL_GameControllerGetBindForAxis(controller2, sdl_axis); + // SDL_GetGamepadBindForAxis was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding.input.axis.axis = sdl_axis; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick2->GetPort(), joystick2->GetGUID(), binding)); continue; } - const auto& binding = SDL_GameControllerGetBindForAxis(controller, sdl_axis); + // SDL_GetGamepadBindForAxis was removed in SDL3 + SDL_GamepadBinding binding{}; + binding.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding.input.axis.axis = sdl_axis; mapping.insert_or_assign( switch_button, BuildParamPackageForBinding(joystick->GetPort(), joystick->GetGUID(), binding)); @@ -953,53 +930,70 @@ AnalogMapping SDLDriver::GetAnalogMappingForDevice(const Common::ParamPackage& p } const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return {}; } AnalogMapping mapping = {}; - const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); - const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); + // SDL_GetGamepadBindForAxis was removed in SDL3 + // We need to work with the underlying joystick directly + SDL_Joystick* sdl_joystick = SDL_GetGamepadJoystick(gamepad); + if (!sdl_joystick) { + return {}; + } + + // For now, use hardcoded axis mappings + SDL_GamepadBinding binding_left_x{}; + binding_left_x.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_left_x.input.axis.axis = 0; // Left stick X + + SDL_GamepadBinding binding_left_y{}; + binding_left_y.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_left_y.input.axis.axis = 1; // Left stick Y + if (params.Has("guid2")) { const auto identifier = joystick2->GetPadIdentifier(); PreSetController(identifier); - PreSetAxis(identifier, binding_left_x.value.axis); - PreSetAxis(identifier, binding_left_y.value.axis); - const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis); - const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis); + PreSetAxis(identifier, binding_left_x.input.axis.axis); + PreSetAxis(identifier, binding_left_y.input.axis.axis); + const auto left_offset_x = -GetAxis(identifier, binding_left_x.input.axis.axis); + const auto left_offset_y = GetAxis(identifier, binding_left_y.input.axis.axis); mapping.insert_or_assign(Settings::NativeAnalog::LStick, - BuildParamPackageForAnalog(identifier, binding_left_x.value.axis, - binding_left_y.value.axis, - left_offset_x, left_offset_y)); + BuildParamPackageForAnalog( + identifier, binding_left_x.input.axis.axis, + binding_left_y.input.axis.axis, left_offset_x, left_offset_y)); } else { const auto identifier = joystick->GetPadIdentifier(); PreSetController(identifier); - PreSetAxis(identifier, binding_left_x.value.axis); - PreSetAxis(identifier, binding_left_y.value.axis); - const auto left_offset_x = -GetAxis(identifier, binding_left_x.value.axis); - const auto left_offset_y = GetAxis(identifier, binding_left_y.value.axis); + PreSetAxis(identifier, binding_left_x.input.axis.axis); + PreSetAxis(identifier, binding_left_y.input.axis.axis); + const auto left_offset_x = -GetAxis(identifier, binding_left_x.input.axis.axis); + const auto left_offset_y = GetAxis(identifier, binding_left_y.input.axis.axis); mapping.insert_or_assign(Settings::NativeAnalog::LStick, - BuildParamPackageForAnalog(identifier, binding_left_x.value.axis, - binding_left_y.value.axis, - left_offset_x, left_offset_y)); + BuildParamPackageForAnalog( + identifier, binding_left_x.input.axis.axis, + binding_left_y.input.axis.axis, left_offset_x, left_offset_y)); } - const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); - const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); + + // For right stick + SDL_GamepadBinding binding_right_x{}; + binding_right_x.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_right_x.input.axis.axis = 2; // Right stick X + + SDL_GamepadBinding binding_right_y{}; + binding_right_y.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; + binding_right_y.input.axis.axis = 3; // Right stick Y const auto identifier = joystick->GetPadIdentifier(); PreSetController(identifier); - PreSetAxis(identifier, binding_right_x.value.axis); - PreSetAxis(identifier, binding_right_y.value.axis); - const auto right_offset_x = -GetAxis(identifier, binding_right_x.value.axis); - const auto right_offset_y = GetAxis(identifier, binding_right_y.value.axis); + PreSetAxis(identifier, binding_right_x.input.axis.axis); + PreSetAxis(identifier, binding_right_y.input.axis.axis); + const auto right_offset_x = -GetAxis(identifier, binding_right_x.input.axis.axis); + const auto right_offset_y = GetAxis(identifier, binding_right_y.input.axis.axis); mapping.insert_or_assign(Settings::NativeAnalog::RStick, - BuildParamPackageForAnalog(identifier, binding_right_x.value.axis, - binding_right_y.value.axis, right_offset_x, - right_offset_y)); + BuildParamPackageForAnalog(identifier, binding_right_x.input.axis.axis, + binding_right_y.input.axis.axis, + right_offset_x, right_offset_y)); return mapping; } @@ -1009,8 +1003,8 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p } const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); const auto joystick2 = GetSDLJoystickByGUID(params.Get("guid2", ""), params.Get("port", 0)); - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return {}; } @@ -1039,7 +1033,6 @@ MotionMapping SDLDriver::GetMotionMappingForDevice(const Common::ParamPackage& p Common::Input::ButtonNames SDLDriver::GetUIName(const Common::ParamPackage& params) const { if (params.Has("button")) { - // TODO(German77): Find how to substitute the values for real button names return Common::Input::ButtonNames::Value; } if (params.Has("hat")) { @@ -1097,29 +1090,27 @@ bool SDLDriver::IsStickInverted(const Common::ParamPackage& params) { if (joystick == nullptr) { return false; } - auto* controller = joystick->GetSDLGameController(); - if (controller == nullptr) { + auto* gamepad = joystick->GetSDLGamepad(); + if (gamepad == nullptr) { return false; } const auto& axis_x = params.Get("axis_x", 0); const auto& axis_y = params.Get("axis_y", 0); - const auto& binding_left_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTX); - const auto& binding_right_x = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTX); - const auto& binding_left_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_LEFTY); - const auto& binding_right_y = - SDL_GameControllerGetBindForAxis(controller, SDL_GAMEPAD_AXIS_RIGHTY); + // SDL_GetGamepadBindForAxis was removed in SDL3 + // Use hardcoded axis mappings for now + const int binding_left_x = 0; // Left stick X + const int binding_right_x = 2; // Right stick X + const int binding_left_y = 1; // Left stick Y + const int binding_right_y = 3; // Right stick Y - if (axis_x != binding_left_y.value.axis && axis_x != binding_right_y.value.axis) { + if (axis_x != binding_left_y && axis_x != binding_right_y) { return false; } - if (axis_y != binding_left_x.value.axis && axis_y != binding_right_x.value.axis) { + if (axis_y != binding_left_x && axis_y != binding_right_x) { return false; } return true; } -} // namespace InputCommon +} // namespace InputCommon \ No newline at end of file diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index bdd2476cb0..98f29e488a 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -15,39 +15,26 @@ #include "input_common/input_engine.h" union SDL_Event; -using SDL_Gamepad = struct _SDL_GameController; -using SDL_Joystick = struct _SDL_Joystick; -using SDL_JoystickID = s32; +using SDL_Gamepad = struct SDL_Gamepad; +using SDL_Joystick = struct SDL_Joystick; +using SDL_JoystickID = Uint32; namespace InputCommon { class SDLJoystick; -using ButtonBindings = - std::array, 20>; -using ZButtonBindings = - std::array, 2>; +using ButtonBindings = std::array, 20>; +using ZButtonBindings = std::array, 2>; class SDLDriver : public InputEngine { public: - /// Initializes and registers SDL device factories explicit SDLDriver(std::string input_engine_); - - /// Unregisters SDL device factories and shut them down. ~SDLDriver() override; void PumpEvents() const; - - /// Handle SDL_Events for joysticks from SDL_PollEvent void HandleGameControllerEvent(const SDL_Event& event); - /// Get the nth joystick with the corresponding GUID std::shared_ptr GetSDLJoystickBySDLID(SDL_JoystickID sdl_id); - - /** - * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so - * tie it to a SDLJoystick with the same guid and that port - */ std::shared_ptr GetSDLJoystickByGUID(const Common::UUID& guid, int port); std::shared_ptr GetSDLJoystickByGUID(const std::string& guid, int port); @@ -69,59 +56,40 @@ public: bool IsVibrationEnabled(const PadIdentifier& identifier) override; private: - void InitJoystick(int joystick_index); + void InitJoystick(SDL_JoystickID joystick_id); void CloseJoystick(SDL_Joystick* sdl_joystick); - - /// Needs to be called before SDL_QuitSubSystem. void CloseJoysticks(); - - /// Takes all vibrations from the queue and sends the command to the controller void SendVibrations(); Common::ParamPackage BuildAnalogParamPackageForButton(int port, const Common::UUID& guid, s32 axis, float value = 0.1f) const; Common::ParamPackage BuildButtonParamPackageForButton(int port, const Common::UUID& guid, s32 button) const; - Common::ParamPackage BuildHatParamPackageForButton(int port, const Common::UUID& guid, s32 hat, u8 value) const; - Common::ParamPackage BuildMotionParam(int port, const Common::UUID& guid) const; - - Common::ParamPackage BuildParamPackageForBinding( - int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const; - + Common::ParamPackage BuildParamPackageForBinding(int port, const Common::UUID& guid, + const SDL_GamepadBinding& binding) const; Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, int axis_y, float offset_x, float offset_y) const; - /// Returns the default button bindings list ButtonBindings GetDefaultButtonBinding(const std::shared_ptr& joystick) const; - - /// Returns the button mappings from a single controller ButtonMapping GetSingleControllerMapping(const std::shared_ptr& joystick, const ButtonBindings& switch_to_sdl_button, const ZButtonBindings& switch_to_sdl_axis) const; - - /// Returns the button mappings from two different controllers ButtonMapping GetDualControllerMapping(const std::shared_ptr& joystick, const std::shared_ptr& joystick2, const ButtonBindings& switch_to_sdl_button, const ZButtonBindings& switch_to_sdl_axis) const; - - /// Returns true if the button is on the left joycon bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; - /// Queue of vibration request to controllers Common::SPSCQueue vibration_queue; - - /// Map of GUID of a list of corresponding virtual Joysticks std::unordered_map>> joystick_map; std::mutex joystick_map_mutex; bool start_thread = false; std::atomic initialized = false; - std::thread vibration_thread; }; -} // namespace InputCommon +} // namespace InputCommon \ No newline at end of file From dd1f699d9d0905ca03d6d9f2c0d62ebb2135f805 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 23/30] windowing and input stuff --- src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 115 +++++++++--------- src/yuzu_cmd/emu_window/emu_window_sdl2.h | 12 +- .../emu_window/emu_window_sdl2_gl.cpp | 31 +++-- src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h | 9 +- .../emu_window/emu_window_sdl2_null.cpp | 17 ++- .../emu_window/emu_window_sdl2_null.h | 6 +- .../emu_window/emu_window_sdl2_vk.cpp | 95 +++++++-------- src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h | 6 +- src/yuzu_cmd/yuzu.cpp | 8 +- 9 files changed, 139 insertions(+), 160 deletions(-) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index cb3e4bc576..38754fe7f0 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -4,7 +4,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include - +#include +#include #include "common/logging/log.h" #include "common/scm_rev.h" #include "common/settings.h" @@ -18,23 +19,23 @@ #include "yuzu_cmd/emu_window/emu_window_sdl2.h" #include "yuzu_cmd/yuzu_icon.h" -EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) +EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) : input_subsystem{input_subsystem_}, system{system_} { input_subsystem->Initialize(); - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) { - LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}, Exiting...", SDL_GetError()); + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD)) { + LOG_CRITICAL(Frontend, "Failed to initialize SDL3: {}, Exiting...", SDL_GetError()); exit(1); } SDL_SetMainReady(); } -EmuWindow_SDL2::~EmuWindow_SDL2() { +EmuWindow_SDL3::~EmuWindow_SDL3() { system.HIDCore().UnloadInputDevices(); input_subsystem->Shutdown(); SDL_Quit(); } -InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const { +InputCommon::MouseButton EmuWindow_SDL3::SDLButtonToMouseButton(u32 button) const { switch (button) { case SDL_BUTTON_LEFT: return InputCommon::MouseButton::Left; @@ -52,21 +53,17 @@ InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) cons } /// @brief Translates pixel position to float position -EmuWindow_SDL2::FloatPairNonHFA EmuWindow_SDL2::MouseToTouchPos(s32 touch_x, s32 touch_y) const { +EmuWindow_SDL3::FloatPairNonHFA EmuWindow_SDL3::MouseToTouchPos(s32 touch_x, s32 touch_y) const { int w = 0, h = 0; SDL_GetWindowSize(render_window, &w, &h); const float fx = float(touch_x) / w; const float fy = float(touch_y) / h; - return { - std::clamp(fx, 0.0f, 1.0f), - std::clamp(fy, 0.0f, 1.0f), - 0 - }; + return {std::clamp(fx, 0.0f, 1.0f), std::clamp(fy, 0.0f, 1.0f), 0}; } -void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { +void EmuWindow_SDL3::OnMouseButton(u32 button, bool pressed, s32 x, s32 y) { const auto mouse_button = SDLButtonToMouseButton(button); - if (state == SDL_PRESSED) { + if (pressed) { auto const [touch_x, touch_y, _] = MouseToTouchPos(x, y); input_subsystem->GetMouse()->PressButton(x, y, mouse_button); input_subsystem->GetMouse()->PressMouseButton(mouse_button); @@ -76,64 +73,65 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { } } -void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { +void EmuWindow_SDL3::OnMouseMotion(s32 x, s32 y) { auto const [touch_x, touch_y, _] = MouseToTouchPos(x, y); input_subsystem->GetMouse()->Move(x, y, 0, 0); input_subsystem->GetMouse()->MouseMove(touch_x, touch_y); input_subsystem->GetMouse()->TouchMove(touch_x, touch_y); } -void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) { +void EmuWindow_SDL3::OnFingerDown(float x, float y, std::size_t id) { input_subsystem->GetTouchScreen()->TouchPressed(x, y, id); } -void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) { +void EmuWindow_SDL3::OnFingerMotion(float x, float y, std::size_t id) { input_subsystem->GetTouchScreen()->TouchMoved(x, y, id); } -void EmuWindow_SDL2::OnFingerUp() { +void EmuWindow_SDL3::OnFingerUp() { input_subsystem->GetTouchScreen()->ReleaseAllTouch(); } -void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { - if (state == SDL_PRESSED) { +void EmuWindow_SDL3::OnKeyEvent(int key, bool pressed) { + if (pressed) { input_subsystem->GetKeyboard()->PressKey(static_cast(key)); - } else if (state == SDL_RELEASED) { + } else { input_subsystem->GetKeyboard()->ReleaseKey(static_cast(key)); } } -bool EmuWindow_SDL2::IsOpen() const { +bool EmuWindow_SDL3::IsOpen() const { return is_open; } -bool EmuWindow_SDL2::IsShown() const { +bool EmuWindow_SDL3::IsShown() const { return is_shown; } -void EmuWindow_SDL2::OnResize() { +void EmuWindow_SDL3::OnResize() { int width, height; - SDL_GL_GetDrawableSize(render_window, &width, &height); + SDL_GetWindowSizeInPixels(render_window, &width, &height); UpdateCurrentFramebufferLayout(width, height); } -void EmuWindow_SDL2::ShowCursor(bool show_cursor) { - SDL_ShowCursor(show_cursor ? SDL_ENABLE : SDL_DISABLE); +void EmuWindow_SDL3::ShowCursor(bool show_cursor) { + show_cursor ? SDL_ShowCursor() : SDL_HideCursor(); } -void EmuWindow_SDL2::Fullscreen() { - SDL_DisplayMode display_mode; +void EmuWindow_SDL3::Fullscreen() { + const SDL_DisplayMode* display_mode; switch (Settings::values.fullscreen_mode.GetValue()) { case Settings::FullscreenMode::Exclusive: - // Set window size to render size before entering fullscreen -- SDL2 does not resize window + // Set window size to render size before entering fullscreen -- SDL3 does not resize window // to display dimensions automatically in this mode. - if (SDL_GetDesktopDisplayMode(0, &display_mode) == 0) { - SDL_SetWindowSize(render_window, display_mode.w, display_mode.h); + display_mode = SDL_GetDesktopDisplayMode(0); + if (display_mode) { + SDL_SetWindowSize(render_window, display_mode->w, display_mode->h); } else { LOG_ERROR(Frontend, "SDL_GetDesktopDisplayMode failed: {}", SDL_GetError()); } - if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) { + if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN)) { return; } @@ -141,7 +139,7 @@ void EmuWindow_SDL2::Fullscreen() { LOG_INFO(Frontend, "Attempting to use borderless fullscreen..."); [[fallthrough]]; case Settings::FullscreenMode::Borderless: - if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) { + if (SDL_SetWindowFullscreen(render_window, true)) { return; } @@ -156,11 +154,13 @@ void EmuWindow_SDL2::Fullscreen() { } } -void EmuWindow_SDL2::WaitEvent() { +void EmuWindow_SDL3::WaitEvent() { // Called on main thread SDL_Event event; - if (!SDL_WaitEvent(&event)) { + if (SDL_WaitEvent(&event)) { + // Event received successfully + } else { const char* error = SDL_GetError(); if (!error || strcmp(error, "") == 0) { // https://github.com/libsdl-org/SDL/issues/5780 @@ -174,27 +174,23 @@ void EmuWindow_SDL2::WaitEvent() { } switch (event.type) { - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: - case SDL_EVENT_WINDOW_RESIZED: - case SDL_EVENT_WINDOW_MAXIMIZED: - case SDL_EVENT_WINDOW_RESTORED: - OnResize(); - break; - case SDL_EVENT_WINDOW_MINIMIZED: - case SDL_EVENT_WINDOW_EXPOSED: - is_shown = event.window.event == SDL_EVENT_WINDOW_EXPOSED; - OnResize(); - break; - case SDL_EVENT_WINDOW_CLOSE_REQUESTED: - is_open = false; - break; - } + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_MAXIMIZED: + case SDL_EVENT_WINDOW_RESTORED: + OnResize(); + break; + case SDL_EVENT_WINDOW_MINIMIZED: + case SDL_EVENT_WINDOW_EXPOSED: + is_shown = event.type == SDL_EVENT_WINDOW_EXPOSED; + OnResize(); + break; + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + is_open = false; break; case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: - OnKeyEvent(static_cast(event.key.keysym.scancode), event.key.state); + OnKeyEvent(static_cast(event.key.scancode), event.type == SDL_EVENT_KEY_DOWN); break; case SDL_EVENT_MOUSE_MOTION: // ignore if it came from touch @@ -205,16 +201,17 @@ void EmuWindow_SDL2::WaitEvent() { case SDL_EVENT_MOUSE_BUTTON_UP: // ignore if it came from touch if (event.button.which != SDL_TOUCH_MOUSEID) { - OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); + OnMouseButton(event.button.button, event.type == SDL_EVENT_MOUSE_BUTTON_DOWN, + event.button.x, event.button.y); } break; case SDL_EVENT_FINGER_DOWN: OnFingerDown(event.tfinger.x, event.tfinger.y, - static_cast(event.tfinger.touchId)); + static_cast(event.tfinger.touchID)); break; case SDL_EVENT_FINGER_MOTION: OnFingerMotion(event.tfinger.x, event.tfinger.y, - static_cast(event.tfinger.touchId)); + static_cast(event.tfinger.touchID)); break; case SDL_EVENT_FINGER_UP: OnFingerUp(); @@ -241,7 +238,7 @@ void EmuWindow_SDL2::WaitEvent() { } // Credits to Samantas5855 and others for this function. -void EmuWindow_SDL2::SetWindowIcon() { +void EmuWindow_SDL3::SetWindowIcon() { SDL_IOStream* const yuzu_icon_stream = SDL_IOFromConstMem((void*)yuzu_icon, yuzu_icon_size); if (yuzu_icon_stream == nullptr) { LOG_WARNING(Frontend, "Failed to create Eden icon stream."); @@ -257,6 +254,6 @@ void EmuWindow_SDL2::SetWindowIcon() { SDL_DestroySurface(window_icon); } -void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair minimal_size) { +void EmuWindow_SDL3::OnMinimalClientAreaChangeRequest(std::pair minimal_size) { SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 8aec1efda0..1e330afc59 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h @@ -22,10 +22,10 @@ class InputSubsystem; enum class MouseButton; } // namespace InputCommon -class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { +class EmuWindow_SDL3 : public Core::Frontend::EmuWindow { public: - explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_); - ~EmuWindow_SDL2(); + explicit EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_); + ~EmuWindow_SDL3(); /// Whether the window is still open, and a close request hasn't yet been sent bool IsOpen() const; @@ -41,7 +41,7 @@ public: protected: /// Called by WaitEvent when a key is pressed or released. - void OnKeyEvent(int key, u8 state); + void OnKeyEvent(int key, bool pressed); /// Converts a SDL mouse button into MouseInput mouse button InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const; @@ -53,7 +53,7 @@ protected: FloatPairNonHFA MouseToTouchPos(s32 touch_x, s32 touch_y) const; /// Called by WaitEvent when a mouse button is pressed or released - void OnMouseButton(u32 button, u8 state, s32 x, s32 y); + void OnMouseButton(u32 button, bool pressed, s32 x, s32 y); /// Called by WaitEvent when the mouse moves. void OnMouseMotion(s32 x, s32 y); @@ -85,7 +85,7 @@ protected: /// Is the window being shown? bool is_shown = true; - /// Internal SDL2 render window + /// Internal SDL3 render window SDL_Window* render_window{}; /// Keeps track of how often to update the title bar during gameplay diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index e08e843673..4e00fa91a8 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -4,7 +4,6 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include #include @@ -16,7 +15,6 @@ #include "common/logging/log.h" #include "common/scm_rev.h" #include "common/settings.h" -#include "common/string_util.h" #include "core/core.h" #include "input_common/main.h" #include "video_core/renderer_base.h" @@ -58,7 +56,7 @@ private: bool is_current = false; }; -bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { +bool EmuWindow_SDL3_GL::SupportsRequiredGLExtensions() { std::vector unsupported_ext; // Extensions required to support some texture formats. @@ -76,9 +74,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { return unsupported_ext.empty(); } -EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_, +EmuWindow_SDL3_GL::EmuWindow_SDL3_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) - : EmuWindow_SDL2{input_subsystem_, system_} { + : EmuWindow_SDL3{input_subsystem_, system_} { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); @@ -95,15 +93,12 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste std::string window_title = fmt::format("{} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); - render_window = - SDL_CreateWindow(window_title.c_str(), - SDL_WINDOWPOS_UNDEFINED, // x position - SDL_WINDOWPOS_UNDEFINED, // y position - Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); + render_window = SDL_CreateWindow( + window_title.c_str(), Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); if (render_window == nullptr) { - LOG_CRITICAL(Frontend, "Failed to create SDL2 window! {}", SDL_GetError()); + LOG_CRITICAL(Frontend, "Failed to create SDL3 window! {}", SDL_GetError()); exit(1); } @@ -120,15 +115,17 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste core_context = CreateSharedContext(); if (window_context == nullptr) { - LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context: {}", SDL_GetError()); + LOG_CRITICAL(Frontend, "Failed to create SDL3 GL context: {}", SDL_GetError()); exit(1); } if (core_context == nullptr) { - LOG_CRITICAL(Frontend, "Failed to create shared SDL2 GL context: {}", SDL_GetError()); + LOG_CRITICAL(Frontend, "Failed to create shared SDL3 GL context: {}", SDL_GetError()); exit(1); } - if (!gladLoadGLLoader(static_cast(SDL_GL_GetProcAddress))) { + if (!gladLoadGLLoader([](const char* name) -> void* { + return reinterpret_cast(SDL_GL_GetProcAddress(name)); + })) { LOG_CRITICAL(Frontend, "Failed to initialize GL functions! {}", SDL_GetError()); exit(1); } @@ -146,11 +143,11 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste Settings::LogSettings(); } -EmuWindow_SDL2_GL::~EmuWindow_SDL2_GL() { +EmuWindow_SDL3_GL::~EmuWindow_SDL3_GL() { core_context.reset(); SDL_GL_DestroyContext(window_context); } -std::unique_ptr EmuWindow_SDL2_GL::CreateSharedContext() const { +std::unique_ptr EmuWindow_SDL3_GL::CreateSharedContext() const { return std::make_unique(render_window); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h index 39346e7047..345ee17760 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "core/frontend/emu_window.h" #include "yuzu_cmd/emu_window/emu_window_sdl2.h" @@ -15,11 +16,11 @@ namespace InputCommon { class InputSubsystem; } -class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { +class EmuWindow_SDL3_GL final : public EmuWindow_SDL3 { public: - explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, + explicit EmuWindow_SDL3_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen); - ~EmuWindow_SDL2_GL(); + ~EmuWindow_SDL3_GL(); std::unique_ptr CreateSharedContext() const override; @@ -27,8 +28,6 @@ private: /// Whether the GPU and driver supports the OpenGL extension required bool SupportsRequiredGLExtensions(); - using SDL_GLContext = void*; - /// The OpenGL context associated with the window SDL_GLContext window_context; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp index cd1003a10e..36f61bd6f1 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp @@ -12,7 +12,7 @@ #include "video_core/renderer_null/renderer_null.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" -#ifdef YUZU_USE_EXTERNAL_SDL2 +#ifdef YUZU_USE_EXTERNAL_SDL3 // Include this before SDL.h to prevent the external from including a dummy #define USING_GENERATED_CONFIG_H #include @@ -20,15 +20,14 @@ #include -EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, +EmuWindow_SDL3_Null::EmuWindow_SDL3_Null(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) - : EmuWindow_SDL2{input_subsystem_, system_} { + : EmuWindow_SDL3{input_subsystem_, system_} { const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc); - render_window = - SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); + render_window = SDL_CreateWindow(window_title.c_str(), Layout::ScreenUndocked::Width, + Layout::ScreenUndocked::Height, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SetWindowIcon(); @@ -44,8 +43,8 @@ EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subs Common::g_scm_branch, Common::g_scm_desc); } -EmuWindow_SDL2_Null::~EmuWindow_SDL2_Null() = default; +EmuWindow_SDL3_Null::~EmuWindow_SDL3_Null() = default; -std::unique_ptr EmuWindow_SDL2_Null::CreateSharedContext() const { +std::unique_ptr EmuWindow_SDL3_Null::CreateSharedContext() const { return std::make_unique(); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h index 35aee286df..f194d137ae 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h @@ -16,11 +16,11 @@ namespace InputCommon { class InputSubsystem; } -class EmuWindow_SDL2_Null final : public EmuWindow_SDL2 { +class EmuWindow_SDL3_Null final : public EmuWindow_SDL3 { public: - explicit EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, + explicit EmuWindow_SDL3_Null(InputCommon::InputSubsystem* input_subsystem_, Core::System& system, bool fullscreen); - ~EmuWindow_SDL2_Null() override; + ~EmuWindow_SDL3_Null() override; std::unique_ptr CreateSharedContext() const override; }; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index 3b3382556b..ee43f130ce 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp @@ -9,31 +9,18 @@ #include "common/logging/log.h" #include "common/scm_rev.h" -#include "video_core/renderer_vulkan/renderer_vulkan.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" #include -#include -EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, +EmuWindow_SDL3_VK::EmuWindow_SDL3_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_, bool fullscreen) - : EmuWindow_SDL2{input_subsystem_, system_} { - const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", - Common::g_build_name, - Common::g_scm_branch, - Common::g_scm_desc); - render_window = - SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, - SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); - - SDL_SysWMinfo wm; - SDL_VERSION(&wm.version); - if (SDL_GetWindowWMInfo(render_window, &wm) == false) { - LOG_CRITICAL(Frontend, "Failed to get information from the window manager: {}", - SDL_GetError()); - std::exit(EXIT_FAILURE); - } + : EmuWindow_SDL3{input_subsystem_, system_} { + const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", Common::g_build_name, + Common::g_scm_branch, Common::g_scm_desc); + render_window = SDL_CreateWindow(window_title.c_str(), Layout::ScreenUndocked::Width, + Layout::ScreenUndocked::Height, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); SetWindowIcon(); @@ -42,43 +29,43 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste ShowCursor(false); } - switch (wm.subsystem) { -#ifdef SDL_VIDEO_DRIVER_WINDOWS - case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS: + { + SDL_PropertiesID props = SDL_GetWindowProperties(render_window); + +#if defined(SDL_PLATFORM_WIN32) window_info.type = Core::Frontend::WindowSystemType::Windows; - window_info.render_surface = reinterpret_cast(wm.info.win.window); - break; -#endif -#ifdef SDL_VIDEO_DRIVER_X11 - case SDL_SYSWM_TYPE::SDL_SYSWM_X11: - window_info.type = Core::Frontend::WindowSystemType::X11; - window_info.display_connection = wm.info.x11.display; - window_info.render_surface = reinterpret_cast(wm.info.x11.window); - break; -#endif -#ifdef SDL_VIDEO_DRIVER_WAYLAND - case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: - window_info.type = Core::Frontend::WindowSystemType::Wayland; - window_info.display_connection = wm.info.wl.display; - window_info.render_surface = wm.info.wl.surface; - break; -#endif -#ifdef SDL_VIDEO_DRIVER_COCOA - case SDL_SYSWM_TYPE::SDL_SYSWM_COCOA: + window_info.render_surface = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); +#elif defined(SDL_PLATFORM_MACOS) window_info.type = Core::Frontend::WindowSystemType::Cocoa; window_info.render_surface = SDL_Metal_CreateView(render_window); - break; -#endif -#ifdef SDL_VIDEO_DRIVER_ANDROID - case SDL_SYSWM_TYPE::SDL_SYSWM_ANDROID: +#elif defined(SDL_PLATFORM_LINUX) + const char* video_driver = SDL_GetCurrentVideoDriver(); + if (video_driver && SDL_strcmp(video_driver, "x11") == 0) { + window_info.type = Core::Frontend::WindowSystemType::X11; + window_info.display_connection = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr); + window_info.render_surface = reinterpret_cast( + SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0)); + } else if (video_driver && SDL_strcmp(video_driver, "wayland") == 0) { + window_info.type = Core::Frontend::WindowSystemType::Wayland; + window_info.display_connection = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr); + window_info.render_surface = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr); + } else { + LOG_CRITICAL(Frontend, "Unsupported SDL video driver: {}", + video_driver ? video_driver : "(null)"); + std::exit(EXIT_FAILURE); + } +#elif defined(SDL_PLATFORM_ANDROID) window_info.type = Core::Frontend::WindowSystemType::Android; - window_info.render_surface = reinterpret_cast(wm.info.android.window); - break; -#endif - default: - LOG_CRITICAL(Frontend, "Window manager subsystem {} not implemented", wm.subsystem); + window_info.render_surface = + SDL_GetPointerProperty(props, SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr); +#else + LOG_CRITICAL(Frontend, "Unsupported platform for SDL window properties"); std::exit(EXIT_FAILURE); - break; +#endif } OnResize(); @@ -88,8 +75,8 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste Common::g_scm_branch, Common::g_scm_desc); } -EmuWindow_SDL2_VK::~EmuWindow_SDL2_VK() = default; +EmuWindow_SDL3_VK::~EmuWindow_SDL3_VK() = default; -std::unique_ptr EmuWindow_SDL2_VK::CreateSharedContext() const { +std::unique_ptr EmuWindow_SDL3_VK::CreateSharedContext() const { return std::make_unique(); } diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h index 9467d164a4..00cc406943 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h @@ -16,11 +16,11 @@ namespace InputCommon { class InputSubsystem; } -class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { +class EmuWindow_SDL3_VK final : public EmuWindow_SDL3 { public: - explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system, + explicit EmuWindow_SDL3_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system, bool fullscreen); - ~EmuWindow_SDL2_VK() override; + ~EmuWindow_SDL3_VK() override; std::unique_ptr CreateSharedContext() const override; }; diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 4a99f34861..96689c49f6 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -346,16 +346,16 @@ int main(int argc, char** argv) { // Apply the command line arguments system.ApplySettings(); - std::unique_ptr emu_window; + std::unique_ptr emu_window; switch (Settings::values.renderer_backend.GetValue()) { case Settings::RendererBackend::OpenGL: - emu_window = std::make_unique(&input_subsystem, system, fullscreen); + emu_window = std::make_unique(&input_subsystem, system, fullscreen); break; case Settings::RendererBackend::Vulkan: - emu_window = std::make_unique(&input_subsystem, system, fullscreen); + emu_window = std::make_unique(&input_subsystem, system, fullscreen); break; case Settings::RendererBackend::Null: - emu_window = std::make_unique(&input_subsystem, system, fullscreen); + emu_window = std::make_unique(&input_subsystem, system, fullscreen); break; } From 6bd49a41c40baf74d8f3c92b7219aa59a78ee6ca Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 21:04:31 +0200 Subject: [PATCH 24/30] rename more macros --- .ci/windows/build.sh | 2 +- docs/Caveats.md | 2 +- docs/Deps.md | 6 +++--- docs/Options.md | 8 ++++---- externals/gamemode/gamemode_client.h | 2 +- src/audio_core/sink/sink_details.cpp | 6 +++--- src/input_common/main.cpp | 20 ++++++++++---------- src/yuzu/main.cpp | 8 ++++---- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.ci/windows/build.sh b/.ci/windows/build.sh index d554e00e1b..c0e46d219f 100644 --- a/.ci/windows/build.sh +++ b/.ci/windows/build.sh @@ -24,7 +24,7 @@ cmake .. -G Ninja \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE:-Release}" \ -DENABLE_QT_TRANSLATION=ON \ -DUSE_DISCORD_PRESENCE=ON \ - -DYUZU_USE_BUNDLED_SDL2=ON \ + -DYUZU_USE_BUNDLED_SDL3=ON \ -DBUILD_TESTING=OFF \ -DYUZU_TESTS=OFF \ -DDYNARMIC_TESTS=OFF \ diff --git a/docs/Caveats.md b/docs/Caveats.md index 7bc2428bab..b60cfd4ea9 100644 --- a/docs/Caveats.md +++ b/docs/Caveats.md @@ -38,7 +38,7 @@ export LIBGL_ALWAYS_SOFTWARE=1 ``` - Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`). -- If using OpenIndiana, due to a bug in SDL2's CMake configuration, audio driver defaults to SunOS ``, which does not exist on OpenIndiana. Using external or bundled SDL2 may solve this. +- If using OpenIndiana, due to a bug in SDL3's CMake configuration, audio driver defaults to SunOS ``, which does not exist on OpenIndiana. Using external or bundled SDL3 may solve this. - System OpenSSL generally does not work. Instead, use `-DYUZU_USE_BUNDLED_OPENSSL=ON` to use a bundled static OpenSSL, or build a system dependency from source. ## OpenBSD diff --git a/docs/Deps.md b/docs/Deps.md index 573d1fe14a..928f9b4d41 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -32,7 +32,7 @@ If you are on Windows and NOT building with MSYS2, you may go [back home](Build. The following are handled by Eden's externals: * [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`) -* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL2=ON` OR `-DYUZU_USE_BUNDLED_SDL2=ON` to reduce compile time) +* [SDL3](https://github.com/libsdl-org/SDL/releases) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL3=ON` OR `-DYUZU_USE_BUNDLED_SDL3=ON` to reduce compile time) All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only): @@ -116,7 +116,7 @@ sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel ``` * Force system libraries via CMake arguments: - * SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF` + * SDL3: `-DYUZU_USE_BUNDLED_SDL3=OFF -DYUZU_USE_EXTERNAL_SDL3=OFF` * FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF` * [RPM Fusion](https://rpmfusion.org/) is required for `ffmpeg-devel` * Fedora 32 or later is required. @@ -202,7 +202,7 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l * Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`) * Download and install all dependencies using: - * `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` + * `pacman -Syu git make mingw-w64-x86_64-SDL3 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` * Add MinGW binaries to the PATH: * `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc` * Add VulkanSDK to the PATH: diff --git a/docs/Options.md b/docs/Options.md index dc73fecd3e..7323fdc4a3 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -40,10 +40,10 @@ Notes: * Unavailable on OpenBSD The following options are desktop only: -- `ENABLE_SDL3` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) +- `ENABLE_SDL3` (ON) Enable the SDL3 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) * Unavailable on Android -- `YUZU_USE_EXTERNAL_SDL2` (ON for non-UNIX) Compiles SDL2 from source -- `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2 +- `YUZU_USE_EXTERNAL_SDL3` (ON for non-UNIX) Compiles SDL3 from source +- `YUZU_USE_BUNDLED_SDL3` (ON for MSVC) Download a prebuilt SDL3 * Unavailable on OpenBSD * Only enabled if YUZU_USE_CPM and ENABLE_SDL3 are both ON - `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED) @@ -62,7 +62,7 @@ The following options are desktop only: - `YUZU_ROOM` (ON) Enable dedicated room functionality - `YUZU_ROOM_STANDALONE` (ON) Enable standalone room executable (eden-room) * Requires `YUZU_ROOM` -- `YUZU_CMD` (ON) Compile the SDL2 frontend (eden-cli) - requires SDL2 +- `YUZU_CMD` (ON) Compile the SDL3 frontend (eden-cli) - requires SDL3 - `YUZU_CRASH_DUMPS` Compile crash dump (Minidump) support" * Currently only available on Windows and Linux diff --git a/externals/gamemode/gamemode_client.h b/externals/gamemode/gamemode_client.h index b9f64fe460..5bda6d26f8 100644 --- a/externals/gamemode/gamemode_client.h +++ b/externals/gamemode/gamemode_client.h @@ -89,7 +89,7 @@ static char internal_gamemode_client_error_string[512] = { 0 }; /** * Load libgamemode dynamically to dislodge us from most dependencies. * This allows clients to link and/or use this regardless of runtime. - * See SDL2 for an example of the reasoning behind this in terms of + * See SDL3 for an example of the reasoning behind this in terms of * dynamic versioning as well. */ static volatile int internal_libgamemode_loaded = 1; diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 70bf75018b..6076ed9eb0 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp @@ -16,7 +16,7 @@ #ifdef HAVE_CUBEB #include "audio_core/sink/cubeb_sink.h" #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 #include "audio_core/sink/sdl2_sink.h" #endif #include "audio_core/sink/null_sink.h" @@ -71,7 +71,7 @@ constexpr SinkDetails sink_details[] = { &GetCubebLatency, }, #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 SinkDetails{ Settings::AudioEngine::Sdl2, [](std::string_view device_id) -> std::unique_ptr { @@ -115,7 +115,7 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) { // BEGIN REINTRODUCED FROM 3833 - REPLACED CODE BLOCK ABOVE - DIABLO 3 FIX // Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which // causes audio issues, in that case go with SDL. -#if defined(HAVE_CUBEB) && defined(HAVE_SDL2) +#if defined(HAVE_CUBEB) && defined(HAVE_SDL3) iter = find_backend(Settings::AudioEngine::Cubeb); if (iter->latency() > TargetSampleCount * 3) { iter = find_backend(Settings::AudioEngine::Sdl2); diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 62a7ae40f8..97a86a750a 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -22,7 +22,7 @@ #ifdef HAVE_LIBUSB #include "input_common/drivers/gc_adapter.h" #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 #include "input_common/drivers/joycon.h" #include "input_common/drivers/sdl_driver.h" #endif @@ -87,7 +87,7 @@ struct InputSubsystem::Impl { #endif RegisterEngine("virtual_amiibo", virtual_amiibo); RegisterEngine("virtual_gamepad", virtual_gamepad); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 RegisterEngine("sdl", sdl); RegisterEngine("joycon", joycon); #endif @@ -121,7 +121,7 @@ struct InputSubsystem::Impl { #endif UnregisterEngine(virtual_amiibo); UnregisterEngine(virtual_gamepad); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 UnregisterEngine(sdl); UnregisterEngine(joycon); #endif @@ -151,7 +151,7 @@ struct InputSubsystem::Impl { #endif auto udp_devices = udp_client->GetInputDevices(); devices.insert(devices.end(), udp_devices.begin(), udp_devices.end()); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 auto joycon_devices = joycon->GetInputDevices(); devices.insert(devices.end(), joycon_devices.begin(), joycon_devices.end()); auto sdl_devices = sdl->GetInputDevices(); @@ -186,7 +186,7 @@ struct InputSubsystem::Impl { if (engine == udp_client->GetEngineName()) { return udp_client; } -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 if (engine == sdl->GetEngineName()) { return sdl; } @@ -277,7 +277,7 @@ struct InputSubsystem::Impl { if (engine == virtual_gamepad->GetEngineName()) { return true; } -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 if (engine == sdl->GetEngineName()) { return true; } @@ -298,7 +298,7 @@ struct InputSubsystem::Impl { gcadapter->BeginConfiguration(); #endif udp_client->BeginConfiguration(); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 sdl->BeginConfiguration(); joycon->BeginConfiguration(); #endif @@ -314,7 +314,7 @@ struct InputSubsystem::Impl { gcadapter->EndConfiguration(); #endif udp_client->EndConfiguration(); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 sdl->EndConfiguration(); joycon->EndConfiguration(); #endif @@ -322,7 +322,7 @@ struct InputSubsystem::Impl { void PumpEvents() const { update_engine->PumpEvents(); -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 sdl->PumpEvents(); #endif } @@ -347,7 +347,7 @@ struct InputSubsystem::Impl { std::shared_ptr gcadapter; #endif -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 std::shared_ptr sdl; std::shared_ptr joycon; #endif diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 58c1b151e2..a80177a038 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -95,7 +95,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include #include -#ifdef HAVE_SDL2 +#ifdef HAVE_SDL3 #include #include #include // For SDL ScreenSaver functions @@ -584,7 +584,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) VkDeviceInfo::PopulateRecords(vk_device_records, this->window()->windowHandle()); } -#if defined(HAVE_SDL2) && !defined(_WIN32) +#if defined(HAVE_SDL3) && !defined(_WIN32) SDL_InitSubSystem(SDL_INIT_VIDEO); // Set a screensaver inhibition reason string. Currently passed to DBus by SDL and visible to @@ -1855,7 +1855,7 @@ void GMainWindow::OnSigInterruptNotifierActivated() { void GMainWindow::PreventOSSleep() { #ifdef _WIN32 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); -#elif defined(HAVE_SDL2) +#elif defined(HAVE_SDL3) SDL_DisableScreenSaver(); #endif } @@ -1863,7 +1863,7 @@ void GMainWindow::PreventOSSleep() { void GMainWindow::AllowOSSleep() { #ifdef _WIN32 SetThreadExecutionState(ES_CONTINUOUS); -#elif defined(HAVE_SDL2) +#elif defined(HAVE_SDL3) SDL_EnableScreenSaver(); #endif } From c26d8175996c048345ff8e569586e8ce27e1a8d4 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:02:49 +0200 Subject: [PATCH 25/30] repo name typo --- cpmfile.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpmfile.json b/cpmfile.json index 8c596b67ba..84df8420fc 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -177,7 +177,7 @@ "ci": true, "package": "SDL3", "name": "SDL3", - "repo": "libsdl-org/SDL3", + "repo": "libsdl-org/SDL", "version": "3.2.22", "min_version": "3.2.0", "cmake_filename": "sdl3" From a2a2ba7e86ee97e86b4cc5bef607cb1d6b324fdc Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:11:55 +0200 Subject: [PATCH 26/30] rename remaining files and vars --- docs/Deps.md | 10 +++++----- src/audio_core/CMakeLists.txt | 4 ++-- .../sink/{sdl2_sink.cpp => sdl3_sink.cpp} | 2 +- src/audio_core/sink/{sdl2_sink.h => sdl3_sink.h} | 0 src/audio_core/sink/sink_details.cpp | 6 +++--- src/common/settings_enums.h | 4 ++-- src/frontend_common/config.cpp | 2 +- src/yuzu_cmd/CMakeLists.txt | 16 ++++++++-------- .../{emu_window_sdl2.cpp => emu_window_sdl3.cpp} | 2 +- .../{emu_window_sdl2.h => emu_window_sdl3.h} | 0 ...window_sdl2_gl.cpp => emu_window_sdl3_gl.cpp} | 2 +- ...emu_window_sdl2_gl.h => emu_window_sdl3_gl.h} | 2 +- ...ow_sdl2_null.cpp => emu_window_sdl3_null.cpp} | 2 +- ...window_sdl2_null.h => emu_window_sdl3_null.h} | 2 +- ...window_sdl2_vk.cpp => emu_window_sdl3_vk.cpp} | 2 +- ...emu_window_sdl2_vk.h => emu_window_sdl3_vk.h} | 2 +- src/yuzu_cmd/yuzu.cpp | 8 ++++---- 17 files changed, 33 insertions(+), 33 deletions(-) rename src/audio_core/sink/{sdl2_sink.cpp => sdl3_sink.cpp} (99%) rename src/audio_core/sink/{sdl2_sink.h => sdl3_sink.h} (100%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2.cpp => emu_window_sdl3.cpp} (99%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2.h => emu_window_sdl3.h} (100%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_gl.cpp => emu_window_sdl3_gl.cpp} (98%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_gl.h => emu_window_sdl3_gl.h} (95%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_null.cpp => emu_window_sdl3_null.cpp} (96%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_null.h => emu_window_sdl3_null.h} (92%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_vk.cpp => emu_window_sdl3_vk.cpp} (98%) rename src/yuzu_cmd/emu_window/{emu_window_sdl2_vk.h => emu_window_sdl3_vk.h} (92%) diff --git a/docs/Deps.md b/docs/Deps.md index 928f9b4d41..b58b6ee053 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -89,7 +89,7 @@ Click on the arrows to expand. Arch Linux ```sh -sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip zydis zycore vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers +sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl3 zlib zstd zip unzip zydis zycore vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers ``` * Building with QT Web Engine requires `qt6-webengine` as well. @@ -129,7 +129,7 @@ sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel Install dependencies from **[Homebrew](https://brew.sh/)** ```sh -brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools +brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl3 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools ``` If you are compiling on Intel Mac, or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` with `/usr/local`. @@ -146,7 +146,7 @@ brew install molten-vk vulkan-loader ``` devel/cmake -devel/sdl20 +devel/sdl30 devel/boost-libs devel/catch2 devel/libfmt @@ -180,7 +180,7 @@ If using FreeBSD 12 or prior, use `devel/pkg-config` instead. ```sh pkg_add -u -pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl2 libusb1.1.0.27 +pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl3 libusb1.1.0.27 ```
@@ -194,7 +194,7 @@ Run the usual update + install of essential toolings: `sudo pkg update && sudo p - **gcc**: `sudo pkg install developer/gcc-14`. - **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`. -Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`. +Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl3 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`.
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 77ac05c7a2..23ffe7f053 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -249,8 +249,8 @@ endif() if (ENABLE_SDL3) target_sources(audio_core PRIVATE - sink/sdl2_sink.cpp - sink/sdl2_sink.h + sink/sdl3_sink.cpp + sink/sdl3_sink.h ) target_link_libraries(audio_core PRIVATE SDL3::SDL3) diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl3_sink.cpp similarity index 99% rename from src/audio_core/sink/sdl2_sink.cpp rename to src/audio_core/sink/sdl3_sink.cpp index 2d07a35c43..563fe0f0ce 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl3_sink.cpp @@ -11,7 +11,7 @@ #include #include "audio_core/common/common.h" -#include "audio_core/sink/sdl2_sink.h" +#include "audio_core/sink/sdl3_sink.h" #include "audio_core/sink/sink_stream.h" #include "common/logging/log.h" #include "core/core.h" diff --git a/src/audio_core/sink/sdl2_sink.h b/src/audio_core/sink/sdl3_sink.h similarity index 100% rename from src/audio_core/sink/sdl2_sink.h rename to src/audio_core/sink/sdl3_sink.h diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp index 6076ed9eb0..3c2b3bf9c6 100644 --- a/src/audio_core/sink/sink_details.cpp +++ b/src/audio_core/sink/sink_details.cpp @@ -17,7 +17,7 @@ #include "audio_core/sink/cubeb_sink.h" #endif #ifdef HAVE_SDL3 -#include "audio_core/sink/sdl2_sink.h" +#include "audio_core/sink/sdl3_sink.h" #endif #include "audio_core/sink/null_sink.h" #include "common/logging/log.h" @@ -73,7 +73,7 @@ constexpr SinkDetails sink_details[] = { #endif #ifdef HAVE_SDL3 SinkDetails{ - Settings::AudioEngine::Sdl2, + Settings::AudioEngine::Sdl3, [](std::string_view device_id) -> std::unique_ptr { return std::make_unique(device_id); }, @@ -118,7 +118,7 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) { #if defined(HAVE_CUBEB) && defined(HAVE_SDL3) iter = find_backend(Settings::AudioEngine::Cubeb); if (iter->latency() > TargetSampleCount * 3) { - iter = find_backend(Settings::AudioEngine::Sdl2); + iter = find_backend(Settings::AudioEngine::Sdl3); } #else iter = std::begin(sink_details); diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 0e5a08d845..89fc83299c 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -92,11 +92,11 @@ struct EnumMetadata { // AudioEngine must be specified discretely due to having existing but slightly different // canonicalizations // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id -enum class AudioEngine : u32 { Auto, Cubeb, Sdl2, Null, Oboe, }; +enum class AudioEngine : u32 { Auto, Cubeb, Sdl3, Null, Oboe, }; template<> inline std::vector> EnumMetadata::Canonicalizations() { return { - {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2}, + {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl3", AudioEngine::Sdl3}, {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe}, }; } diff --git a/src/frontend_common/config.cpp b/src/frontend_common/config.cpp index fa1383436e..a0b2af5c8c 100644 --- a/src/frontend_common/config.cpp +++ b/src/frontend_common/config.cpp @@ -51,7 +51,7 @@ void Config::Initialize(const std::string& config_name) { void Config::Initialize(const std::optional config_path) { const std::filesystem::path default_sdl_config_path = - FS::GetEdenPath(FS::EdenPath::ConfigDir) / "sdl2-config.ini"; + FS::GetEdenPath(FS::EdenPath::ConfigDir) / "sdl3-config.ini"; config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path)); void(FS::CreateParentDir(config_loc)); SetUpIni(); diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index 47e0f7e5e1..f62f4b49e3 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -16,14 +16,14 @@ function(create_resource file output filename) endfunction() add_executable(yuzu-cmd - emu_window/emu_window_sdl2.cpp - emu_window/emu_window_sdl2.h - emu_window/emu_window_sdl2_gl.cpp - emu_window/emu_window_sdl2_gl.h - emu_window/emu_window_sdl2_null.cpp - emu_window/emu_window_sdl2_null.h - emu_window/emu_window_sdl2_vk.cpp - emu_window/emu_window_sdl2_vk.h + emu_window/emu_window_sdl3.cpp + emu_window/emu_window_sdl3.h + emu_window/emu_window_sdl3_gl.cpp + emu_window/emu_window_sdl3_gl.h + emu_window/emu_window_sdl3_null.cpp + emu_window/emu_window_sdl3_null.h + emu_window/emu_window_sdl3_vk.cpp + emu_window/emu_window_sdl3_vk.h precompiled_headers.h sdl_config.cpp sdl_config.h diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp similarity index 99% rename from src/yuzu_cmd/emu_window/emu_window_sdl2.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3.cpp index 38754fe7f0..5988c130c0 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp @@ -16,7 +16,7 @@ #include "input_common/drivers/mouse.h" #include "input_common/drivers/touch_screen.h" #include "input_common/main.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" #include "yuzu_cmd/yuzu_icon.h" EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl3.h similarity index 100% rename from src/yuzu_cmd/emu_window/emu_window_sdl2.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3.h diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.cpp similarity index 98% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3_gl.cpp index 4e00fa91a8..6eb9c1445c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.cpp @@ -18,7 +18,7 @@ #include "core/core.h" #include "input_common/main.h" #include "video_core/renderer_base.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_gl.h" class SDLGLContext : public Core::Frontend::GraphicsContext { public: diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.h similarity index 95% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3_gl.h index 345ee17760..5b664d5314 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_gl.h @@ -6,7 +6,7 @@ #include #include #include "core/frontend/emu_window.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" namespace Core { class System; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.cpp similarity index 96% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3_null.cpp index 36f61bd6f1..0704862061 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.cpp @@ -10,7 +10,7 @@ #include "common/logging/log.h" #include "common/scm_rev.h" #include "video_core/renderer_null/renderer_null.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_null.h" #ifdef YUZU_USE_EXTERNAL_SDL3 // Include this before SDL.h to prevent the external from including a dummy diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.h similarity index 92% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_null.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3_null.h index f194d137ae..6f43cc7997 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_null.h @@ -6,7 +6,7 @@ #include #include "core/frontend/emu_window.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" namespace Core { class System; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.cpp similarity index 98% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp rename to src/yuzu_cmd/emu_window/emu_window_sdl3_vk.cpp index ee43f130ce..dada5d308e 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.cpp @@ -9,7 +9,7 @@ #include "common/logging/log.h" #include "common/scm_rev.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_vk.h" #include diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.h similarity index 92% rename from src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h rename to src/yuzu_cmd/emu_window/emu_window_sdl3_vk.h index 00cc406943..df6fc391ad 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl3_vk.h @@ -6,7 +6,7 @@ #include #include "core/frontend/emu_window.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" namespace Core { class System; diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 96689c49f6..68c1edeaed 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -34,10 +34,10 @@ #include "network/network.h" #include "sdl_config.h" #include "video_core/renderer_base.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" -#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_gl.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_null.h" +#include "yuzu_cmd/emu_window/emu_window_sdl3_vk.h" #ifdef _WIN32 // windows.h needs to be included before shellapi.h From e73fdc88310fe34b6bfa31e5454dd9c782955168 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:17:52 +0200 Subject: [PATCH 27/30] remove steamdeck sdl dep --- CMakeLists.txt | 7 +------ cpmfile.json | 8 -------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a690ebd119..da4363308b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -633,12 +633,7 @@ if (ENABLE_SDL3) set(SDL_FILE ON) endif() - if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") - set(SDL_PIPEWIRE OFF) # build errors out with this on - AddJsonPackage("sdl3_steamdeck") - else() - AddJsonPackage("sdl3_generic") - endif() + AddJsonPackage("sdl3_generic") elseif (YUZU_USE_BUNDLED_SDL3) message(STATUS "Using bundled SDL3") AddJsonPackage(sdl3) diff --git a/cpmfile.json b/cpmfile.json index 84df8420fc..fdaa17b7b3 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -165,14 +165,6 @@ "key": "generic", "bundled": true }, - "sdl3_steamdeck": { - "package": "SDL3", - "repo": "libsdl-org/SDL", - "sha": "cc016b0046", - "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", - "key": "steamdeck", - "bundled": true - }, "sdl3": { "ci": true, "package": "SDL3", From b393574b7e02c05c63e2760b98b02abdebe13a02 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:18:09 +0200 Subject: [PATCH 28/30] do not require latest --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da4363308b..ae300cc4bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -639,7 +639,7 @@ if (ENABLE_SDL3) AddJsonPackage(sdl3) endif() - find_package(SDL3 3.2.22 REQUIRED) + find_package(SDL3 3.2.12 REQUIRED) endif() # List of all FFmpeg components required From 2c8f8a409ed9d3192fcecc456caa8946a727d4f7 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:22:19 +0200 Subject: [PATCH 29/30] doc typos --- docs/Deps.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Deps.md b/docs/Deps.md index b58b6ee053..49f72b7b97 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -32,7 +32,7 @@ If you are on Windows and NOT building with MSYS2, you may go [back home](Build. The following are handled by Eden's externals: * [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`) -* [SDL3](https://github.com/libsdl-org/SDL/releases) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL3=ON` OR `-DYUZU_USE_BUNDLED_SDL3=ON` to reduce compile time) +* [SDL3](https://github.com/libsdl-org/SDL/releases) 3.2.12+ (should use `-DYUZU_USE_EXTERNAL_SDL3=ON` OR `-DYUZU_USE_BUNDLED_SDL3=ON` to reduce compile time) All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only): @@ -202,7 +202,7 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l * Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`) * Download and install all dependencies using: - * `pacman -Syu git make mingw-w64-x86_64-SDL3 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` + * `pacman -Syu git make mingw-w64-x86_64-sdl3 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` * Add MinGW binaries to the PATH: * `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc` * Add VulkanSDK to the PATH: From 4c5aaf7f13c54b0fcedda21cf2c4950edf3703d1 Mon Sep 17 00:00:00 2001 From: octocar Date: Wed, 1 Oct 2025 22:22:59 +0200 Subject: [PATCH 30/30] unused include --- src/input_common/drivers/sdl_driver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index d140b00ca0..fb3e376c63 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -8,7 +8,6 @@ #include "common/param_package.h" #include "common/settings.h" #include "common/thread.h" -// #include "common/vector_math.h" // Not used directly #include "input_common/drivers/sdl_driver.h" namespace InputCommon {