diff options
Diffstat (limited to 'src')
31 files changed, 342 insertions, 102 deletions
diff --git a/src/common/bit_util.h b/src/common/bit_util.h index eef8c1c5a..f50d3308a 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h | |||
| @@ -46,6 +46,12 @@ template <typename T> | |||
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | template <typename T> | 48 | template <typename T> |
| 49 | requires std::is_unsigned_v<T> | ||
| 50 | [[nodiscard]] constexpr bool IsPow2(T value) { | ||
| 51 | return std::has_single_bit(value); | ||
| 52 | } | ||
| 53 | |||
| 54 | template <typename T> | ||
| 49 | requires std::is_integral_v<T> | 55 | requires std::is_integral_v<T> |
| 50 | [[nodiscard]] T NextPow2(T value) { | 56 | [[nodiscard]] T NextPow2(T value) { |
| 51 | return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); | 57 | return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U))); |
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index 62010d762..81b212e4b 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp | |||
| @@ -124,7 +124,10 @@ void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) { | |||
| 124 | 124 | ||
| 125 | // "from" might no longer be valid if the thread was killed | 125 | // "from" might no longer be valid if the thread was killed |
| 126 | if (auto from = weak_from.lock()) { | 126 | if (auto from = weak_from.lock()) { |
| 127 | ASSERT(from->impl->previous_fiber != nullptr); | 127 | if (from->impl->previous_fiber == nullptr) { |
| 128 | ASSERT_MSG(false, "previous_fiber is nullptr!"); | ||
| 129 | return; | ||
| 130 | } | ||
| 128 | from->impl->previous_fiber->impl->context = transfer.fctx; | 131 | from->impl->previous_fiber->impl->context = transfer.fctx; |
| 129 | from->impl->previous_fiber->impl->guard.unlock(); | 132 | from->impl->previous_fiber->impl->guard.unlock(); |
| 130 | from->impl->previous_fiber.reset(); | 133 | from->impl->previous_fiber.reset(); |
diff --git a/src/common/input.h b/src/common/input.h index f775a4c01..f4f9eb30a 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -209,6 +209,13 @@ enum class ButtonNames { | |||
| 209 | Triangle, | 209 | Triangle, |
| 210 | Share, | 210 | Share, |
| 211 | Options, | 211 | Options, |
| 212 | |||
| 213 | // Mouse buttons | ||
| 214 | ButtonMouseWheel, | ||
| 215 | ButtonBackward, | ||
| 216 | ButtonForward, | ||
| 217 | ButtonTask, | ||
| 218 | ButtonExtra, | ||
| 212 | }; | 219 | }; |
| 213 | 220 | ||
| 214 | // Callback data consisting of an input type and the equivalent data status | 221 | // Callback data consisting of an input type and the equivalent data status |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b1a746727..6e8d11919 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -247,6 +247,9 @@ add_library(core STATIC | |||
| 247 | hle/kernel/k_trace.h | 247 | hle/kernel/k_trace.h |
| 248 | hle/kernel/k_transfer_memory.cpp | 248 | hle/kernel/k_transfer_memory.cpp |
| 249 | hle/kernel/k_transfer_memory.h | 249 | hle/kernel/k_transfer_memory.h |
| 250 | hle/kernel/k_worker_task.h | ||
| 251 | hle/kernel/k_worker_task_manager.cpp | ||
| 252 | hle/kernel/k_worker_task_manager.h | ||
| 250 | hle/kernel/k_writable_event.cpp | 253 | hle/kernel/k_writable_event.cpp |
| 251 | hle/kernel/k_writable_event.h | 254 | hle/kernel/k_writable_event.h |
| 252 | hle/kernel/kernel.cpp | 255 | hle/kernel/kernel.cpp |
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index 08f8af551..eef0ff493 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp | |||
| @@ -158,7 +158,7 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { | |||
| 158 | auto& motion = console.motion_state; | 158 | auto& motion = console.motion_state; |
| 159 | motion.accel = emulated.GetAcceleration(); | 159 | motion.accel = emulated.GetAcceleration(); |
| 160 | motion.gyro = emulated.GetGyroscope(); | 160 | motion.gyro = emulated.GetGyroscope(); |
| 161 | motion.rotation = emulated.GetGyroscope(); | 161 | motion.rotation = emulated.GetRotations(); |
| 162 | motion.orientation = emulated.GetOrientation(); | 162 | motion.orientation = emulated.GetOrientation(); |
| 163 | motion.quaternion = emulated.GetQuaternion(); | 163 | motion.quaternion = emulated.GetQuaternion(); |
| 164 | motion.gyro_bias = emulated.GetGyroBias(); | 164 | motion.gyro_bias = emulated.GetGyroBias(); |
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 13edb7332..d12037b11 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -145,7 +145,7 @@ void EmulatedController::LoadDevices() { | |||
| 145 | motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); | 145 | motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); |
| 146 | std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), | 146 | std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), |
| 147 | Common::Input::CreateDevice<Common::Input::InputDevice>); | 147 | Common::Input::CreateDevice<Common::Input::InputDevice>); |
| 148 | std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(), | 148 | std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(), |
| 149 | Common::Input::CreateDevice<Common::Input::InputDevice>); | 149 | Common::Input::CreateDevice<Common::Input::InputDevice>); |
| 150 | std::transform(output_params.begin(), output_params.end(), output_devices.begin(), | 150 | std::transform(output_params.begin(), output_params.end(), output_devices.begin(), |
| 151 | Common::Input::CreateDevice<Common::Input::OutputDevice>); | 151 | Common::Input::CreateDevice<Common::Input::OutputDevice>); |
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index f5acff6e0..860aab400 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp | |||
| @@ -114,7 +114,7 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu | |||
| 114 | if (TransformToButton(callback).value) { | 114 | if (TransformToButton(callback).value) { |
| 115 | std::random_device device; | 115 | std::random_device device; |
| 116 | std::mt19937 gen(device()); | 116 | std::mt19937 gen(device()); |
| 117 | std::uniform_int_distribution<s16> distribution(-1000, 1000); | 117 | std::uniform_int_distribution<s16> distribution(-5000, 5000); |
| 118 | status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | 118 | status.accel.x.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; |
| 119 | status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | 119 | status.accel.y.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; |
| 120 | status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; | 120 | status.accel.z.raw_value = static_cast<f32>(distribution(gen)) * 0.001f; |
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index 0166df0a5..1b44541b1 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp | |||
| @@ -8,12 +8,16 @@ | |||
| 8 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/scope_exit.h" | 10 | #include "common/scope_exit.h" |
| 11 | #include "core/core.h" | ||
| 12 | #include "core/device_memory.h" | ||
| 11 | #include "core/hle/kernel/k_memory_manager.h" | 13 | #include "core/hle/kernel/k_memory_manager.h" |
| 12 | #include "core/hle/kernel/k_page_linked_list.h" | 14 | #include "core/hle/kernel/k_page_linked_list.h" |
| 13 | #include "core/hle/kernel/svc_results.h" | 15 | #include "core/hle/kernel/svc_results.h" |
| 14 | 16 | ||
| 15 | namespace Kernel { | 17 | namespace Kernel { |
| 16 | 18 | ||
| 19 | KMemoryManager::KMemoryManager(Core::System& system_) : system{system_} {} | ||
| 20 | |||
| 17 | std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) { | 21 | std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) { |
| 18 | const auto size{end_address - start_address}; | 22 | const auto size{end_address - start_address}; |
| 19 | 23 | ||
| @@ -81,7 +85,7 @@ VAddr KMemoryManager::AllocateAndOpenContinuous(std::size_t num_pages, std::size | |||
| 81 | } | 85 | } |
| 82 | 86 | ||
| 83 | ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, | 87 | ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, |
| 84 | Direction dir) { | 88 | Direction dir, u32 heap_fill_value) { |
| 85 | ASSERT(page_list.GetNumPages() == 0); | 89 | ASSERT(page_list.GetNumPages() == 0); |
| 86 | 90 | ||
| 87 | // Early return if we're allocating no pages | 91 | // Early return if we're allocating no pages |
| @@ -139,6 +143,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_ | |||
| 139 | } | 143 | } |
| 140 | } | 144 | } |
| 141 | 145 | ||
| 146 | // Clear allocated memory. | ||
| 147 | for (const auto& it : page_list.Nodes()) { | ||
| 148 | std::memset(system.DeviceMemory().GetPointer(it.GetAddress()), heap_fill_value, | ||
| 149 | it.GetSize()); | ||
| 150 | } | ||
| 151 | |||
| 142 | // Only succeed if we allocated as many pages as we wanted | 152 | // Only succeed if we allocated as many pages as we wanted |
| 143 | if (num_pages) { | 153 | if (num_pages) { |
| 144 | return ResultOutOfMemory; | 154 | return ResultOutOfMemory; |
| @@ -146,11 +156,12 @@ ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_ | |||
| 146 | 156 | ||
| 147 | // We succeeded! | 157 | // We succeeded! |
| 148 | group_guard.Cancel(); | 158 | group_guard.Cancel(); |
| 159 | |||
| 149 | return ResultSuccess; | 160 | return ResultSuccess; |
| 150 | } | 161 | } |
| 151 | 162 | ||
| 152 | ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, | 163 | ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, |
| 153 | Direction dir) { | 164 | Direction dir, u32 heap_fill_value) { |
| 154 | // Early return if we're freeing no pages | 165 | // Early return if we're freeing no pages |
| 155 | if (!num_pages) { | 166 | if (!num_pages) { |
| 156 | return ResultSuccess; | 167 | return ResultSuccess; |
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h index 39badc5f1..abd6c8ace 100644 --- a/src/core/hle/kernel/k_memory_manager.h +++ b/src/core/hle/kernel/k_memory_manager.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "core/hle/kernel/k_page_heap.h" | 12 | #include "core/hle/kernel/k_page_heap.h" |
| 13 | #include "core/hle/result.h" | 13 | #include "core/hle/result.h" |
| 14 | 14 | ||
| 15 | namespace Core { | ||
| 16 | class System; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Kernel { | 19 | namespace Kernel { |
| 16 | 20 | ||
| 17 | class KPageLinkedList; | 21 | class KPageLinkedList; |
| @@ -42,7 +46,7 @@ public: | |||
| 42 | Mask = (0xF << Shift), | 46 | Mask = (0xF << Shift), |
| 43 | }; | 47 | }; |
| 44 | 48 | ||
| 45 | KMemoryManager() = default; | 49 | explicit KMemoryManager(Core::System& system_); |
| 46 | 50 | ||
| 47 | constexpr std::size_t GetSize(Pool pool) const { | 51 | constexpr std::size_t GetSize(Pool pool) const { |
| 48 | return managers[static_cast<std::size_t>(pool)].GetSize(); | 52 | return managers[static_cast<std::size_t>(pool)].GetSize(); |
| @@ -51,10 +55,10 @@ public: | |||
| 51 | void InitializeManager(Pool pool, u64 start_address, u64 end_address); | 55 | void InitializeManager(Pool pool, u64 start_address, u64 end_address); |
| 52 | 56 | ||
| 53 | VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); | 57 | VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); |
| 54 | ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, | 58 | ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir, |
| 55 | Direction dir = Direction::FromFront); | 59 | u32 heap_fill_value = 0); |
| 56 | ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, | 60 | ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, Direction dir, |
| 57 | Direction dir = Direction::FromFront); | 61 | u32 heap_fill_value = 0); |
| 58 | 62 | ||
| 59 | static constexpr std::size_t MaxManagerCount = 10; | 63 | static constexpr std::size_t MaxManagerCount = 10; |
| 60 | 64 | ||
| @@ -129,6 +133,7 @@ private: | |||
| 129 | }; | 133 | }; |
| 130 | 134 | ||
| 131 | private: | 135 | private: |
| 136 | Core::System& system; | ||
| 132 | std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks; | 137 | std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks; |
| 133 | std::array<Impl, MaxManagerCount> managers; | 138 | std::array<Impl, MaxManagerCount> managers; |
| 134 | }; | 139 | }; |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 27d86c9a4..b650ea31d 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -289,8 +289,8 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory | |||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | KPageLinkedList page_linked_list; | 291 | KPageLinkedList page_linked_list; |
| 292 | CASCADE_CODE( | 292 | CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool, |
| 293 | system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); | 293 | allocation_option)); |
| 294 | CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); | 294 | CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); |
| 295 | 295 | ||
| 296 | block_manager->Update(addr, num_pages, state, perm); | 296 | block_manager->Update(addr, num_pages, state, perm); |
| @@ -457,8 +457,8 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 457 | 457 | ||
| 458 | KPageLinkedList page_linked_list; | 458 | KPageLinkedList page_linked_list; |
| 459 | 459 | ||
| 460 | CASCADE_CODE( | 460 | CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, |
| 461 | system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool)); | 461 | memory_pool, allocation_option)); |
| 462 | 462 | ||
| 463 | // We succeeded, so commit the memory reservation. | 463 | // We succeeded, so commit the memory reservation. |
| 464 | memory_reservation.Commit(); | 464 | memory_reservation.Commit(); |
| @@ -541,7 +541,8 @@ ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) { | |||
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | const std::size_t num_pages{size / PageSize}; | 543 | const std::size_t num_pages{size / PageSize}; |
| 544 | system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool); | 544 | system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool, |
| 545 | allocation_option); | ||
| 545 | 546 | ||
| 546 | block_manager->Update(addr, num_pages, KMemoryState::Free); | 547 | block_manager->Update(addr, num_pages, KMemoryState::Free); |
| 547 | 548 | ||
| @@ -960,7 +961,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { | |||
| 960 | // Allocate pages for the heap extension. | 961 | // Allocate pages for the heap extension. |
| 961 | KPageLinkedList page_linked_list; | 962 | KPageLinkedList page_linked_list; |
| 962 | R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize, | 963 | R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize, |
| 963 | memory_pool)); | 964 | memory_pool, allocation_option)); |
| 964 | 965 | ||
| 965 | // Map the pages. | 966 | // Map the pages. |
| 966 | { | 967 | { |
| @@ -1027,8 +1028,8 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, | |||
| 1027 | CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); | 1028 | CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); |
| 1028 | } else { | 1029 | } else { |
| 1029 | KPageLinkedList page_group; | 1030 | KPageLinkedList page_group; |
| 1030 | CASCADE_CODE( | 1031 | CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, |
| 1031 | system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool)); | 1032 | memory_pool, allocation_option)); |
| 1032 | CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); | 1033 | CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); |
| 1033 | } | 1034 | } |
| 1034 | 1035 | ||
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 274644181..f67986e91 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -303,6 +303,7 @@ private: | |||
| 303 | bool is_aslr_enabled{}; | 303 | bool is_aslr_enabled{}; |
| 304 | 304 | ||
| 305 | KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application}; | 305 | KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application}; |
| 306 | KMemoryManager::Direction allocation_option{KMemoryManager::Direction::FromFront}; | ||
| 306 | 307 | ||
| 307 | Common::PageTable page_table_impl; | 308 | Common::PageTable page_table_impl; |
| 308 | 309 | ||
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index cca405fed..265ac6fa1 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -149,6 +149,10 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st | |||
| 149 | return ResultSuccess; | 149 | return ResultSuccess; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void KProcess::DoWorkerTaskImpl() { | ||
| 153 | UNIMPLEMENTED(); | ||
| 154 | } | ||
| 155 | |||
| 152 | KResourceLimit* KProcess::GetResourceLimit() const { | 156 | KResourceLimit* KProcess::GetResourceLimit() const { |
| 153 | return resource_limit; | 157 | return resource_limit; |
| 154 | } | 158 | } |
| @@ -477,7 +481,7 @@ void KProcess::Finalize() { | |||
| 477 | } | 481 | } |
| 478 | 482 | ||
| 479 | // Perform inherited finalization. | 483 | // Perform inherited finalization. |
| 480 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); | 484 | KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize(); |
| 481 | } | 485 | } |
| 482 | 486 | ||
| 483 | /** | 487 | /** |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index e7c8b5838..c2a672021 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "core/hle/kernel/k_condition_variable.h" | 15 | #include "core/hle/kernel/k_condition_variable.h" |
| 16 | #include "core/hle/kernel/k_handle_table.h" | 16 | #include "core/hle/kernel/k_handle_table.h" |
| 17 | #include "core/hle/kernel/k_synchronization_object.h" | 17 | #include "core/hle/kernel/k_synchronization_object.h" |
| 18 | #include "core/hle/kernel/k_worker_task.h" | ||
| 18 | #include "core/hle/kernel/process_capability.h" | 19 | #include "core/hle/kernel/process_capability.h" |
| 19 | #include "core/hle/kernel/slab_helpers.h" | 20 | #include "core/hle/kernel/slab_helpers.h" |
| 20 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| @@ -62,8 +63,7 @@ enum class ProcessStatus { | |||
| 62 | DebugBreak, | 63 | DebugBreak, |
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | class KProcess final | 66 | class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { |
| 66 | : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject> { | ||
| 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); | 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); |
| 68 | 68 | ||
| 69 | public: | 69 | public: |
| @@ -345,6 +345,8 @@ public: | |||
| 345 | 345 | ||
| 346 | bool IsSignaled() const override; | 346 | bool IsSignaled() const override; |
| 347 | 347 | ||
| 348 | void DoWorkerTaskImpl(); | ||
| 349 | |||
| 348 | void PinCurrentThread(s32 core_id); | 350 | void PinCurrentThread(s32 core_id); |
| 349 | void UnpinCurrentThread(s32 core_id); | 351 | void UnpinCurrentThread(s32 core_id); |
| 350 | void UnpinThread(KThread* thread); | 352 | void UnpinThread(KThread* thread); |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 31cec990e..f900b2e7a 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -49,8 +49,6 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul | |||
| 49 | if (!must_context_switch || core != current_core) { | 49 | if (!must_context_switch || core != current_core) { |
| 50 | auto& phys_core = kernel.PhysicalCore(core); | 50 | auto& phys_core = kernel.PhysicalCore(core); |
| 51 | phys_core.Interrupt(); | 51 | phys_core.Interrupt(); |
| 52 | } else { | ||
| 53 | must_context_switch = true; | ||
| 54 | } | 52 | } |
| 55 | cores_pending_reschedule &= ~(1ULL << core); | 53 | cores_pending_reschedule &= ~(1ULL << core); |
| 56 | } | 54 | } |
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 71e029a3f..7a5e6fc08 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "core/hle/kernel/k_system_control.h" | 30 | #include "core/hle/kernel/k_system_control.h" |
| 31 | #include "core/hle/kernel/k_thread.h" | 31 | #include "core/hle/kernel/k_thread.h" |
| 32 | #include "core/hle/kernel/k_thread_queue.h" | 32 | #include "core/hle/kernel/k_thread_queue.h" |
| 33 | #include "core/hle/kernel/k_worker_task_manager.h" | ||
| 33 | #include "core/hle/kernel/kernel.h" | 34 | #include "core/hle/kernel/kernel.h" |
| 34 | #include "core/hle/kernel/svc_results.h" | 35 | #include "core/hle/kernel/svc_results.h" |
| 35 | #include "core/hle/kernel/time_manager.h" | 36 | #include "core/hle/kernel/time_manager.h" |
| @@ -332,7 +333,7 @@ void KThread::Finalize() { | |||
| 332 | } | 333 | } |
| 333 | 334 | ||
| 334 | // Perform inherited finalization. | 335 | // Perform inherited finalization. |
| 335 | KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>::Finalize(); | 336 | KSynchronizationObject::Finalize(); |
| 336 | } | 337 | } |
| 337 | 338 | ||
| 338 | bool KThread::IsSignaled() const { | 339 | bool KThread::IsSignaled() const { |
| @@ -376,11 +377,28 @@ void KThread::StartTermination() { | |||
| 376 | 377 | ||
| 377 | // Register terminated dpc flag. | 378 | // Register terminated dpc flag. |
| 378 | RegisterDpc(DpcFlag::Terminated); | 379 | RegisterDpc(DpcFlag::Terminated); |
| 380 | } | ||
| 381 | |||
| 382 | void KThread::FinishTermination() { | ||
| 383 | // Ensure that the thread is not executing on any core. | ||
| 384 | if (parent != nullptr) { | ||
| 385 | for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) { | ||
| 386 | KThread* core_thread{}; | ||
| 387 | do { | ||
| 388 | core_thread = kernel.Scheduler(i).GetCurrentThread(); | ||
| 389 | } while (core_thread == this); | ||
| 390 | } | ||
| 391 | } | ||
| 379 | 392 | ||
| 380 | // Close the thread. | 393 | // Close the thread. |
| 381 | this->Close(); | 394 | this->Close(); |
| 382 | } | 395 | } |
| 383 | 396 | ||
| 397 | void KThread::DoWorkerTaskImpl() { | ||
| 398 | // Finish the termination that was begun by Exit(). | ||
| 399 | this->FinishTermination(); | ||
| 400 | } | ||
| 401 | |||
| 384 | void KThread::Pin(s32 current_core) { | 402 | void KThread::Pin(s32 current_core) { |
| 385 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 403 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 386 | 404 | ||
| @@ -417,12 +435,7 @@ void KThread::Pin(s32 current_core) { | |||
| 417 | static_cast<u32>(ThreadState::SuspendShift))); | 435 | static_cast<u32>(ThreadState::SuspendShift))); |
| 418 | 436 | ||
| 419 | // Update our state. | 437 | // Update our state. |
| 420 | const ThreadState old_state = thread_state; | 438 | UpdateState(); |
| 421 | thread_state = static_cast<ThreadState>(GetSuspendFlags() | | ||
| 422 | static_cast<u32>(old_state & ThreadState::Mask)); | ||
| 423 | if (thread_state != old_state) { | ||
| 424 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 425 | } | ||
| 426 | } | 439 | } |
| 427 | 440 | ||
| 428 | // TODO(bunnei): Update our SVC access permissions. | 441 | // TODO(bunnei): Update our SVC access permissions. |
| @@ -463,20 +476,13 @@ void KThread::Unpin() { | |||
| 463 | } | 476 | } |
| 464 | 477 | ||
| 465 | // Allow performing thread suspension (if termination hasn't been requested). | 478 | // Allow performing thread suspension (if termination hasn't been requested). |
| 466 | { | 479 | if (!IsTerminationRequested()) { |
| 467 | // Update our allow flags. | 480 | // Update our allow flags. |
| 468 | if (!IsTerminationRequested()) { | 481 | suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) + |
| 469 | suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) + | 482 | static_cast<u32>(ThreadState::SuspendShift))); |
| 470 | static_cast<u32>(ThreadState::SuspendShift))); | ||
| 471 | } | ||
| 472 | 483 | ||
| 473 | // Update our state. | 484 | // Update our state. |
| 474 | const ThreadState old_state = thread_state; | 485 | UpdateState(); |
| 475 | thread_state = static_cast<ThreadState>(GetSuspendFlags() | | ||
| 476 | static_cast<u32>(old_state & ThreadState::Mask)); | ||
| 477 | if (thread_state != old_state) { | ||
| 478 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 479 | } | ||
| 480 | } | 486 | } |
| 481 | 487 | ||
| 482 | // TODO(bunnei): Update our SVC access permissions. | 488 | // TODO(bunnei): Update our SVC access permissions. |
| @@ -689,12 +695,7 @@ void KThread::Resume(SuspendType type) { | |||
| 689 | ~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); | 695 | ~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); |
| 690 | 696 | ||
| 691 | // Update our state. | 697 | // Update our state. |
| 692 | const ThreadState old_state = thread_state; | 698 | this->UpdateState(); |
| 693 | thread_state = static_cast<ThreadState>(GetSuspendFlags() | | ||
| 694 | static_cast<u32>(old_state & ThreadState::Mask)); | ||
| 695 | if (thread_state != old_state) { | ||
| 696 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 697 | } | ||
| 698 | } | 699 | } |
| 699 | 700 | ||
| 700 | void KThread::WaitCancel() { | 701 | void KThread::WaitCancel() { |
| @@ -721,19 +722,22 @@ void KThread::TrySuspend() { | |||
| 721 | ASSERT(GetNumKernelWaiters() == 0); | 722 | ASSERT(GetNumKernelWaiters() == 0); |
| 722 | 723 | ||
| 723 | // Perform the suspend. | 724 | // Perform the suspend. |
| 724 | Suspend(); | 725 | this->UpdateState(); |
| 725 | } | 726 | } |
| 726 | 727 | ||
| 727 | void KThread::Suspend() { | 728 | void KThread::UpdateState() { |
| 728 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 729 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 729 | ASSERT(IsSuspendRequested()); | ||
| 730 | 730 | ||
| 731 | // Set our suspend flags in state. | 731 | // Set our suspend flags in state. |
| 732 | const auto old_state = thread_state; | 732 | const auto old_state = thread_state; |
| 733 | thread_state = static_cast<ThreadState>(GetSuspendFlags()) | (old_state & ThreadState::Mask); | 733 | const auto new_state = |
| 734 | static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask); | ||
| 735 | thread_state = new_state; | ||
| 734 | 736 | ||
| 735 | // Note the state change in scheduler. | 737 | // Note the state change in scheduler. |
| 736 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 738 | if (new_state != old_state) { |
| 739 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 740 | } | ||
| 737 | } | 741 | } |
| 738 | 742 | ||
| 739 | void KThread::Continue() { | 743 | void KThread::Continue() { |
| @@ -998,13 +1002,16 @@ ResultCode KThread::Run() { | |||
| 998 | 1002 | ||
| 999 | // If the current thread has been asked to suspend, suspend it and retry. | 1003 | // If the current thread has been asked to suspend, suspend it and retry. |
| 1000 | if (GetCurrentThread(kernel).IsSuspended()) { | 1004 | if (GetCurrentThread(kernel).IsSuspended()) { |
| 1001 | GetCurrentThread(kernel).Suspend(); | 1005 | GetCurrentThread(kernel).UpdateState(); |
| 1002 | continue; | 1006 | continue; |
| 1003 | } | 1007 | } |
| 1004 | 1008 | ||
| 1005 | // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. | 1009 | // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. |
| 1006 | if (IsUserThread() && IsSuspended()) { | 1010 | if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) { |
| 1007 | Suspend(); | 1011 | if (IsUserThread() && IsSuspended()) { |
| 1012 | this->UpdateState(); | ||
| 1013 | } | ||
| 1014 | owner->IncrementThreadCount(); | ||
| 1008 | } | 1015 | } |
| 1009 | 1016 | ||
| 1010 | // Set our state and finish. | 1017 | // Set our state and finish. |
| @@ -1031,9 +1038,16 @@ void KThread::Exit() { | |||
| 1031 | 1038 | ||
| 1032 | // Disallow all suspension. | 1039 | // Disallow all suspension. |
| 1033 | suspend_allowed_flags = 0; | 1040 | suspend_allowed_flags = 0; |
| 1041 | this->UpdateState(); | ||
| 1042 | |||
| 1043 | // Disallow all suspension. | ||
| 1044 | suspend_allowed_flags = 0; | ||
| 1034 | 1045 | ||
| 1035 | // Start termination. | 1046 | // Start termination. |
| 1036 | StartTermination(); | 1047 | StartTermination(); |
| 1048 | |||
| 1049 | // Register the thread as a work task. | ||
| 1050 | KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); | ||
| 1037 | } | 1051 | } |
| 1038 | } | 1052 | } |
| 1039 | 1053 | ||
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 83dfde69b..cc427f6cf 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "core/hle/kernel/k_light_lock.h" | 19 | #include "core/hle/kernel/k_light_lock.h" |
| 20 | #include "core/hle/kernel/k_spin_lock.h" | 20 | #include "core/hle/kernel/k_spin_lock.h" |
| 21 | #include "core/hle/kernel/k_synchronization_object.h" | 21 | #include "core/hle/kernel/k_synchronization_object.h" |
| 22 | #include "core/hle/kernel/k_worker_task.h" | ||
| 22 | #include "core/hle/kernel/slab_helpers.h" | 23 | #include "core/hle/kernel/slab_helpers.h" |
| 23 | #include "core/hle/kernel/svc_common.h" | 24 | #include "core/hle/kernel/svc_common.h" |
| 24 | #include "core/hle/kernel/svc_types.h" | 25 | #include "core/hle/kernel/svc_types.h" |
| @@ -100,7 +101,7 @@ enum class ThreadWaitReasonForDebugging : u32 { | |||
| 100 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); | 101 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); |
| 101 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); | 102 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); |
| 102 | 103 | ||
| 103 | class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, | 104 | class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>, |
| 104 | public boost::intrusive::list_base_hook<> { | 105 | public boost::intrusive::list_base_hook<> { |
| 105 | KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); | 106 | KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); |
| 106 | 107 | ||
| @@ -192,9 +193,9 @@ public: | |||
| 192 | 193 | ||
| 193 | void TrySuspend(); | 194 | void TrySuspend(); |
| 194 | 195 | ||
| 195 | void Continue(); | 196 | void UpdateState(); |
| 196 | 197 | ||
| 197 | void Suspend(); | 198 | void Continue(); |
| 198 | 199 | ||
| 199 | constexpr void SetSyncedIndex(s32 index) { | 200 | constexpr void SetSyncedIndex(s32 index) { |
| 200 | synced_index = index; | 201 | synced_index = index; |
| @@ -385,6 +386,8 @@ public: | |||
| 385 | 386 | ||
| 386 | void OnTimer(); | 387 | void OnTimer(); |
| 387 | 388 | ||
| 389 | void DoWorkerTaskImpl(); | ||
| 390 | |||
| 388 | static void PostDestroy(uintptr_t arg); | 391 | static void PostDestroy(uintptr_t arg); |
| 389 | 392 | ||
| 390 | [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); | 393 | [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); |
| @@ -679,6 +682,8 @@ private: | |||
| 679 | 682 | ||
| 680 | void StartTermination(); | 683 | void StartTermination(); |
| 681 | 684 | ||
| 685 | void FinishTermination(); | ||
| 686 | |||
| 682 | [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, | 687 | [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, |
| 683 | s32 prio, s32 virt_core, KProcess* owner, ThreadType type); | 688 | s32 prio, s32 virt_core, KProcess* owner, ThreadType type); |
| 684 | 689 | ||
diff --git a/src/core/hle/kernel/k_worker_task.h b/src/core/hle/kernel/k_worker_task.h new file mode 100644 index 000000000..b7794c6a8 --- /dev/null +++ b/src/core/hle/kernel/k_worker_task.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | |||
| 11 | class KWorkerTask : public KSynchronizationObject { | ||
| 12 | public: | ||
| 13 | explicit KWorkerTask(KernelCore& kernel_); | ||
| 14 | |||
| 15 | void DoWorkerTask(); | ||
| 16 | }; | ||
| 17 | |||
| 18 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_worker_task_manager.cpp b/src/core/hle/kernel/k_worker_task_manager.cpp new file mode 100644 index 000000000..785e08111 --- /dev/null +++ b/src/core/hle/kernel/k_worker_task_manager.cpp | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "core/hle/kernel/k_process.h" | ||
| 7 | #include "core/hle/kernel/k_thread.h" | ||
| 8 | #include "core/hle/kernel/k_worker_task.h" | ||
| 9 | #include "core/hle/kernel/k_worker_task_manager.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | KWorkerTask::KWorkerTask(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||
| 15 | |||
| 16 | void KWorkerTask::DoWorkerTask() { | ||
| 17 | if (auto* const thread = this->DynamicCast<KThread*>(); thread != nullptr) { | ||
| 18 | return thread->DoWorkerTaskImpl(); | ||
| 19 | } else { | ||
| 20 | auto* const process = this->DynamicCast<KProcess*>(); | ||
| 21 | ASSERT(process != nullptr); | ||
| 22 | |||
| 23 | return process->DoWorkerTaskImpl(); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "yuzu:KWorkerTaskManager") {} | ||
| 28 | |||
| 29 | void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) { | ||
| 30 | ASSERT(type <= WorkerType::Count); | ||
| 31 | kernel.WorkerTaskManager().AddTask(kernel, task); | ||
| 32 | } | ||
| 33 | |||
| 34 | void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) { | ||
| 35 | KScopedSchedulerLock sl(kernel); | ||
| 36 | m_waiting_thread.QueueWork([task]() { | ||
| 37 | // Do the task. | ||
| 38 | task->DoWorkerTask(); | ||
| 39 | }); | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_worker_task_manager.h b/src/core/hle/kernel/k_worker_task_manager.h new file mode 100644 index 000000000..43d1bfcec --- /dev/null +++ b/src/core/hle/kernel/k_worker_task_manager.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/thread_worker.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | class KernelCore; | ||
| 13 | class KWorkerTask; | ||
| 14 | |||
| 15 | class KWorkerTaskManager final { | ||
| 16 | public: | ||
| 17 | enum class WorkerType : u32 { | ||
| 18 | Exit, | ||
| 19 | Count, | ||
| 20 | }; | ||
| 21 | |||
| 22 | KWorkerTaskManager(); | ||
| 23 | |||
| 24 | static void AddTask(KernelCore& kernel_, WorkerType type, KWorkerTask* task); | ||
| 25 | |||
| 26 | private: | ||
| 27 | void AddTask(KernelCore& kernel, KWorkerTask* task); | ||
| 28 | |||
| 29 | private: | ||
| 30 | Common::ThreadWorker m_waiting_thread; | ||
| 31 | }; | ||
| 32 | |||
| 33 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0b618fb46..887c1fd27 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include "core/hle/kernel/k_shared_memory.h" | 37 | #include "core/hle/kernel/k_shared_memory.h" |
| 38 | #include "core/hle/kernel/k_slab_heap.h" | 38 | #include "core/hle/kernel/k_slab_heap.h" |
| 39 | #include "core/hle/kernel/k_thread.h" | 39 | #include "core/hle/kernel/k_thread.h" |
| 40 | #include "core/hle/kernel/k_worker_task_manager.h" | ||
| 40 | #include "core/hle/kernel/kernel.h" | 41 | #include "core/hle/kernel/kernel.h" |
| 41 | #include "core/hle/kernel/physical_core.h" | 42 | #include "core/hle/kernel/physical_core.h" |
| 42 | #include "core/hle/kernel/service_thread.h" | 43 | #include "core/hle/kernel/service_thread.h" |
| @@ -630,7 +631,7 @@ struct KernelCore::Impl { | |||
| 630 | const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); | 631 | const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); |
| 631 | 632 | ||
| 632 | // Initialize memory managers | 633 | // Initialize memory managers |
| 633 | memory_manager = std::make_unique<KMemoryManager>(); | 634 | memory_manager = std::make_unique<KMemoryManager>(system); |
| 634 | memory_manager->InitializeManager(KMemoryManager::Pool::Application, | 635 | memory_manager->InitializeManager(KMemoryManager::Pool::Application, |
| 635 | application_pool.GetAddress(), | 636 | application_pool.GetAddress(), |
| 636 | application_pool.GetEndAddress()); | 637 | application_pool.GetEndAddress()); |
| @@ -797,6 +798,8 @@ struct KernelCore::Impl { | |||
| 797 | 798 | ||
| 798 | std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; | 799 | std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; |
| 799 | 800 | ||
| 801 | KWorkerTaskManager worker_task_manager; | ||
| 802 | |||
| 800 | // System context | 803 | // System context |
| 801 | Core::System& system; | 804 | Core::System& system; |
| 802 | }; | 805 | }; |
| @@ -1137,6 +1140,14 @@ const Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() const { | |||
| 1137 | return impl->slab_resource_counts; | 1140 | return impl->slab_resource_counts; |
| 1138 | } | 1141 | } |
| 1139 | 1142 | ||
| 1143 | KWorkerTaskManager& KernelCore::WorkerTaskManager() { | ||
| 1144 | return impl->worker_task_manager; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | const KWorkerTaskManager& KernelCore::WorkerTaskManager() const { | ||
| 1148 | return impl->worker_task_manager; | ||
| 1149 | } | ||
| 1150 | |||
| 1140 | bool KernelCore::IsPhantomModeForSingleCore() const { | 1151 | bool KernelCore::IsPhantomModeForSingleCore() const { |
| 1141 | return impl->IsPhantomModeForSingleCore(); | 1152 | return impl->IsPhantomModeForSingleCore(); |
| 1142 | } | 1153 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b9b423908..0e04fc3bb 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -52,6 +52,7 @@ class KSharedMemory; | |||
| 52 | class KSharedMemoryInfo; | 52 | class KSharedMemoryInfo; |
| 53 | class KThread; | 53 | class KThread; |
| 54 | class KTransferMemory; | 54 | class KTransferMemory; |
| 55 | class KWorkerTaskManager; | ||
| 55 | class KWritableEvent; | 56 | class KWritableEvent; |
| 56 | class KCodeMemory; | 57 | class KCodeMemory; |
| 57 | class PhysicalCore; | 58 | class PhysicalCore; |
| @@ -343,6 +344,12 @@ public: | |||
| 343 | /// Gets the current slab resource counts. | 344 | /// Gets the current slab resource counts. |
| 344 | const Init::KSlabResourceCounts& SlabResourceCounts() const; | 345 | const Init::KSlabResourceCounts& SlabResourceCounts() const; |
| 345 | 346 | ||
| 347 | /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks. | ||
| 348 | KWorkerTaskManager& WorkerTaskManager(); | ||
| 349 | |||
| 350 | /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks. | ||
| 351 | const KWorkerTaskManager& WorkerTaskManager() const; | ||
| 352 | |||
| 346 | private: | 353 | private: |
| 347 | friend class KProcess; | 354 | friend class KProcess; |
| 348 | friend class KThread; | 355 | friend class KThread; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 84da38b3b..a2bf7defb 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -1176,7 +1176,8 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) { | |||
| 1176 | 1176 | ||
| 1177 | const auto parameters{rp.PopRaw<Parameters>()}; | 1177 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1178 | 1178 | ||
| 1179 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1179 | GetAppletResource() |
| 1180 | ->GetController<Controller_NPad>(HidController::NPad) | ||
| 1180 | .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp); | 1181 | .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp); |
| 1181 | 1182 | ||
| 1182 | LOG_WARNING(Service_HID, | 1183 | LOG_WARNING(Service_HID, |
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index aa69216c8..d8ae7f0c1 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp | |||
| @@ -16,6 +16,7 @@ constexpr int mouse_axis_x = 0; | |||
| 16 | constexpr int mouse_axis_y = 1; | 16 | constexpr int mouse_axis_y = 1; |
| 17 | constexpr int wheel_axis_x = 2; | 17 | constexpr int wheel_axis_x = 2; |
| 18 | constexpr int wheel_axis_y = 3; | 18 | constexpr int wheel_axis_y = 3; |
| 19 | constexpr int motion_wheel_y = 4; | ||
| 19 | constexpr int touch_axis_x = 10; | 20 | constexpr int touch_axis_x = 10; |
| 20 | constexpr int touch_axis_y = 11; | 21 | constexpr int touch_axis_y = 11; |
| 21 | constexpr PadIdentifier identifier = { | 22 | constexpr PadIdentifier identifier = { |
| @@ -30,8 +31,9 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) | |||
| 30 | PreSetAxis(identifier, mouse_axis_y); | 31 | PreSetAxis(identifier, mouse_axis_y); |
| 31 | PreSetAxis(identifier, wheel_axis_x); | 32 | PreSetAxis(identifier, wheel_axis_x); |
| 32 | PreSetAxis(identifier, wheel_axis_y); | 33 | PreSetAxis(identifier, wheel_axis_y); |
| 34 | PreSetAxis(identifier, motion_wheel_y); | ||
| 33 | PreSetAxis(identifier, touch_axis_x); | 35 | PreSetAxis(identifier, touch_axis_x); |
| 34 | PreSetAxis(identifier, touch_axis_x); | 36 | PreSetAxis(identifier, touch_axis_y); |
| 35 | update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); | 37 | update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); |
| 36 | } | 38 | } |
| 37 | 39 | ||
| @@ -48,6 +50,8 @@ void Mouse::UpdateThread(std::stop_token stop_token) { | |||
| 48 | SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); | 50 | SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); |
| 49 | } | 51 | } |
| 50 | 52 | ||
| 53 | SetAxis(identifier, motion_wheel_y, 0.0f); | ||
| 54 | |||
| 51 | if (mouse_panning_timout++ > 20) { | 55 | if (mouse_panning_timout++ > 20) { |
| 52 | StopPanning(); | 56 | StopPanning(); |
| 53 | } | 57 | } |
| @@ -136,6 +140,7 @@ void Mouse::MouseWheelChange(int x, int y) { | |||
| 136 | wheel_position.y += y; | 140 | wheel_position.y += y; |
| 137 | SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); | 141 | SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); |
| 138 | SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); | 142 | SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y)); |
| 143 | SetAxis(identifier, motion_wheel_y, static_cast<f32>(y) / 100.0f); | ||
| 139 | } | 144 | } |
| 140 | 145 | ||
| 141 | void Mouse::ReleaseAllButtons() { | 146 | void Mouse::ReleaseAllButtons() { |
| @@ -171,13 +176,39 @@ AnalogMapping Mouse::GetAnalogMappingForDevice( | |||
| 171 | return mapping; | 176 | return mapping; |
| 172 | } | 177 | } |
| 173 | 178 | ||
| 179 | Common::Input::ButtonNames Mouse::GetUIButtonName(const Common::ParamPackage& params) const { | ||
| 180 | const auto button = static_cast<MouseButton>(params.Get("button", 0)); | ||
| 181 | switch (button) { | ||
| 182 | case MouseButton::Left: | ||
| 183 | return Common::Input::ButtonNames::ButtonLeft; | ||
| 184 | case MouseButton::Right: | ||
| 185 | return Common::Input::ButtonNames::ButtonRight; | ||
| 186 | case MouseButton::Wheel: | ||
| 187 | return Common::Input::ButtonNames::ButtonMouseWheel; | ||
| 188 | case MouseButton::Backward: | ||
| 189 | return Common::Input::ButtonNames::ButtonBackward; | ||
| 190 | case MouseButton::Forward: | ||
| 191 | return Common::Input::ButtonNames::ButtonForward; | ||
| 192 | case MouseButton::Task: | ||
| 193 | return Common::Input::ButtonNames::ButtonTask; | ||
| 194 | case MouseButton::Extra: | ||
| 195 | return Common::Input::ButtonNames::ButtonExtra; | ||
| 196 | case MouseButton::Undefined: | ||
| 197 | default: | ||
| 198 | return Common::Input::ButtonNames::Undefined; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 174 | Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const { | 202 | Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const { |
| 175 | if (params.Has("button")) { | 203 | if (params.Has("button")) { |
| 176 | return Common::Input::ButtonNames::Value; | 204 | return GetUIButtonName(params); |
| 177 | } | 205 | } |
| 178 | if (params.Has("axis")) { | 206 | if (params.Has("axis")) { |
| 179 | return Common::Input::ButtonNames::Value; | 207 | return Common::Input::ButtonNames::Value; |
| 180 | } | 208 | } |
| 209 | if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) { | ||
| 210 | return Common::Input::ButtonNames::Engine; | ||
| 211 | } | ||
| 181 | 212 | ||
| 182 | return Common::Input::ButtonNames::Invalid; | 213 | return Common::Input::ButtonNames::Invalid; |
| 183 | } | 214 | } |
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 040446178..c5833b8ed 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h | |||
| @@ -69,6 +69,8 @@ private: | |||
| 69 | void UpdateThread(std::stop_token stop_token); | 69 | void UpdateThread(std::stop_token stop_token); |
| 70 | void StopPanning(); | 70 | void StopPanning(); |
| 71 | 71 | ||
| 72 | Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; | ||
| 73 | |||
| 72 | Common::Vec2<int> mouse_origin; | 74 | Common::Vec2<int> mouse_origin; |
| 73 | Common::Vec2<int> last_mouse_position; | 75 | Common::Vec2<int> last_mouse_position; |
| 74 | Common::Vec2<float> last_mouse_change; | 76 | Common::Vec2<float> last_mouse_change; |
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 41701e24d..ed6281772 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp | |||
| @@ -198,9 +198,9 @@ public: | |||
| 198 | if (sdl_controller) { | 198 | if (sdl_controller) { |
| 199 | switch (SDL_GameControllerGetType(sdl_controller.get())) { | 199 | switch (SDL_GameControllerGetType(sdl_controller.get())) { |
| 200 | case SDL_CONTROLLER_TYPE_XBOX360: | 200 | case SDL_CONTROLLER_TYPE_XBOX360: |
| 201 | return "XBox 360 Controller"; | 201 | return "Xbox 360 Controller"; |
| 202 | case SDL_CONTROLLER_TYPE_XBOXONE: | 202 | case SDL_CONTROLLER_TYPE_XBOXONE: |
| 203 | return "XBox One Controller"; | 203 | return "Xbox One Controller"; |
| 204 | case SDL_CONTROLLER_TYPE_PS3: | 204 | case SDL_CONTROLLER_TYPE_PS3: |
| 205 | return "DualShock 3 Controller"; | 205 | return "DualShock 3 Controller"; |
| 206 | case SDL_CONTROLLER_TYPE_PS4: | 206 | case SDL_CONTROLLER_TYPE_PS4: |
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index b57330e51..0508b408d 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp | |||
| @@ -173,7 +173,7 @@ void InputEngine::ResetButtonState() { | |||
| 173 | SetButton(controller.first, button.first, false); | 173 | SetButton(controller.first, button.first, false); |
| 174 | } | 174 | } |
| 175 | for (const auto& button : controller.second.hat_buttons) { | 175 | for (const auto& button : controller.second.hat_buttons) { |
| 176 | SetHatButton(controller.first, button.first, false); | 176 | SetHatButton(controller.first, button.first, 0); |
| 177 | } | 177 | } |
| 178 | } | 178 | } |
| 179 | } | 179 | } |
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp index 6e0024b2d..475257f42 100644 --- a/src/input_common/input_mapping.cpp +++ b/src/input_common/input_mapping.cpp | |||
| @@ -143,6 +143,19 @@ void MappingFactory::RegisterMotion(const MappingData& data) { | |||
| 143 | } | 143 | } |
| 144 | new_input.Set("port", static_cast<int>(data.pad.port)); | 144 | new_input.Set("port", static_cast<int>(data.pad.port)); |
| 145 | new_input.Set("pad", static_cast<int>(data.pad.pad)); | 145 | new_input.Set("pad", static_cast<int>(data.pad.pad)); |
| 146 | |||
| 147 | // If engine is mouse map the mouse position as 3 axis motion | ||
| 148 | if (data.engine == "mouse") { | ||
| 149 | new_input.Set("axis_x", 1); | ||
| 150 | new_input.Set("invert_x", "-"); | ||
| 151 | new_input.Set("axis_y", 0); | ||
| 152 | new_input.Set("axis_z", 4); | ||
| 153 | new_input.Set("range", 1.0f); | ||
| 154 | new_input.Set("deadzone", 0.0f); | ||
| 155 | input_queue.Push(new_input); | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | |||
| 146 | switch (data.type) { | 159 | switch (data.type) { |
| 147 | case EngineInputType::Button: | 160 | case EngineInputType::Button: |
| 148 | case EngineInputType::HatButton: | 161 | case EngineInputType::HatButton: |
diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h index 13ed88382..de5672155 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/command_classes/codecs/codec.h | |||
| @@ -66,7 +66,7 @@ private: | |||
| 66 | bool initialized{}; | 66 | bool initialized{}; |
| 67 | NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None}; | 67 | NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None}; |
| 68 | 68 | ||
| 69 | AVCodec* av_codec{nullptr}; | 69 | const AVCodec* av_codec{nullptr}; |
| 70 | AVCodecContext* av_codec_ctx{nullptr}; | 70 | AVCodecContext* av_codec_ctx{nullptr}; |
| 71 | AVBufferRef* av_gpu_decoder{nullptr}; | 71 | AVBufferRef* av_gpu_decoder{nullptr}; |
| 72 | 72 | ||
diff --git a/src/video_core/host_shaders/astc_decoder.comp b/src/video_core/host_shaders/astc_decoder.comp index f34c5f5d9..3a10578cb 100644 --- a/src/video_core/host_shaders/astc_decoder.comp +++ b/src/video_core/host_shaders/astc_decoder.comp | |||
| @@ -155,9 +155,6 @@ uint SwizzleOffset(uvec2 pos) { | |||
| 155 | // Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)] | 155 | // Replicates low num_bits such that [(to_bit - 1):(to_bit - 1 - from_bit)] |
| 156 | // is the same as [(num_bits - 1):0] and repeats all the way down. | 156 | // is the same as [(num_bits - 1):0] and repeats all the way down. |
| 157 | uint Replicate(uint val, uint num_bits, uint to_bit) { | 157 | uint Replicate(uint val, uint num_bits, uint to_bit) { |
| 158 | if (num_bits == 0 || to_bit == 0) { | ||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | const uint v = val & uint((1 << num_bits) - 1); | 158 | const uint v = val & uint((1 << num_bits) - 1); |
| 162 | uint res = v; | 159 | uint res = v; |
| 163 | uint reslen = num_bits; | 160 | uint reslen = num_bits; |
| @@ -187,42 +184,57 @@ uint ReplicateBitTo9(uint value) { | |||
| 187 | return REPLICATE_1_BIT_TO_9_TABLE[value]; | 184 | return REPLICATE_1_BIT_TO_9_TABLE[value]; |
| 188 | } | 185 | } |
| 189 | 186 | ||
| 190 | uint FastReplicateTo8(uint value, uint num_bits) { | 187 | uint FastReplicate(uint value, uint num_bits, uint to_bit) { |
| 191 | switch (num_bits) { | 188 | if (num_bits == 0) { |
| 192 | case 1: | 189 | return 0; |
| 193 | return REPLICATE_1_BIT_TO_8_TABLE[value]; | 190 | } |
| 194 | case 2: | 191 | if (num_bits == to_bit) { |
| 195 | return REPLICATE_2_BIT_TO_8_TABLE[value]; | ||
| 196 | case 3: | ||
| 197 | return REPLICATE_3_BIT_TO_8_TABLE[value]; | ||
| 198 | case 4: | ||
| 199 | return REPLICATE_4_BIT_TO_8_TABLE[value]; | ||
| 200 | case 5: | ||
| 201 | return REPLICATE_5_BIT_TO_8_TABLE[value]; | ||
| 202 | case 6: | ||
| 203 | return REPLICATE_6_BIT_TO_8_TABLE[value]; | ||
| 204 | case 7: | ||
| 205 | return REPLICATE_7_BIT_TO_8_TABLE[value]; | ||
| 206 | case 8: | ||
| 207 | return value; | 192 | return value; |
| 208 | } | 193 | } |
| 209 | return Replicate(value, num_bits, 8); | 194 | if (to_bit == 6) { |
| 195 | switch (num_bits) { | ||
| 196 | case 1: | ||
| 197 | return REPLICATE_1_BIT_TO_6_TABLE[value]; | ||
| 198 | case 2: | ||
| 199 | return REPLICATE_2_BIT_TO_6_TABLE[value]; | ||
| 200 | case 3: | ||
| 201 | return REPLICATE_3_BIT_TO_6_TABLE[value]; | ||
| 202 | case 4: | ||
| 203 | return REPLICATE_4_BIT_TO_6_TABLE[value]; | ||
| 204 | case 5: | ||
| 205 | return REPLICATE_5_BIT_TO_6_TABLE[value]; | ||
| 206 | default: | ||
| 207 | break; | ||
| 208 | } | ||
| 209 | } else { /* if (to_bit == 8) */ | ||
| 210 | switch (num_bits) { | ||
| 211 | case 1: | ||
| 212 | return REPLICATE_1_BIT_TO_8_TABLE[value]; | ||
| 213 | case 2: | ||
| 214 | return REPLICATE_2_BIT_TO_8_TABLE[value]; | ||
| 215 | case 3: | ||
| 216 | return REPLICATE_3_BIT_TO_8_TABLE[value]; | ||
| 217 | case 4: | ||
| 218 | return REPLICATE_4_BIT_TO_8_TABLE[value]; | ||
| 219 | case 5: | ||
| 220 | return REPLICATE_5_BIT_TO_8_TABLE[value]; | ||
| 221 | case 6: | ||
| 222 | return REPLICATE_6_BIT_TO_8_TABLE[value]; | ||
| 223 | case 7: | ||
| 224 | return REPLICATE_7_BIT_TO_8_TABLE[value]; | ||
| 225 | default: | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | return Replicate(value, num_bits, to_bit); | ||
| 230 | } | ||
| 231 | |||
| 232 | uint FastReplicateTo8(uint value, uint num_bits) { | ||
| 233 | return FastReplicate(value, num_bits, 8); | ||
| 210 | } | 234 | } |
| 211 | 235 | ||
| 212 | uint FastReplicateTo6(uint value, uint num_bits) { | 236 | uint FastReplicateTo6(uint value, uint num_bits) { |
| 213 | switch (num_bits) { | 237 | return FastReplicate(value, num_bits, 6); |
| 214 | case 1: | ||
| 215 | return REPLICATE_1_BIT_TO_6_TABLE[value]; | ||
| 216 | case 2: | ||
| 217 | return REPLICATE_2_BIT_TO_6_TABLE[value]; | ||
| 218 | case 3: | ||
| 219 | return REPLICATE_3_BIT_TO_6_TABLE[value]; | ||
| 220 | case 4: | ||
| 221 | return REPLICATE_4_BIT_TO_6_TABLE[value]; | ||
| 222 | case 5: | ||
| 223 | return REPLICATE_5_BIT_TO_6_TABLE[value]; | ||
| 224 | } | ||
| 225 | return Replicate(value, num_bits, 6); | ||
| 226 | } | 238 | } |
| 227 | 239 | ||
| 228 | uint Div3Floor(uint v) { | 240 | uint Div3Floor(uint v) { |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 3d78efddc..153702c0b 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -1038,7 +1038,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1038 | } | 1038 | } |
| 1039 | if (has_ext_shader_atomic_int64) { | 1039 | if (has_ext_shader_atomic_int64) { |
| 1040 | VkPhysicalDeviceShaderAtomicInt64Features atomic_int64; | 1040 | VkPhysicalDeviceShaderAtomicInt64Features atomic_int64; |
| 1041 | atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; | 1041 | atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES; |
| 1042 | atomic_int64.pNext = nullptr; | 1042 | atomic_int64.pNext = nullptr; |
| 1043 | features.pNext = &atomic_int64; | 1043 | features.pNext = &atomic_int64; |
| 1044 | physical.GetFeatures2KHR(features); | 1044 | physical.GetFeatures2KHR(features); |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index b9342466e..d2132b408 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -102,6 +102,16 @@ QString GetButtonName(Common::Input::ButtonNames button_name) { | |||
| 102 | return QObject::tr("Share"); | 102 | return QObject::tr("Share"); |
| 103 | case Common::Input::ButtonNames::Options: | 103 | case Common::Input::ButtonNames::Options: |
| 104 | return QObject::tr("Options"); | 104 | return QObject::tr("Options"); |
| 105 | case Common::Input::ButtonNames::ButtonMouseWheel: | ||
| 106 | return QObject::tr("Wheel", "Indicates the mouse wheel"); | ||
| 107 | case Common::Input::ButtonNames::ButtonBackward: | ||
| 108 | return QObject::tr("Backward"); | ||
| 109 | case Common::Input::ButtonNames::ButtonForward: | ||
| 110 | return QObject::tr("Forward"); | ||
| 111 | case Common::Input::ButtonNames::ButtonTask: | ||
| 112 | return QObject::tr("Task"); | ||
| 113 | case Common::Input::ButtonNames::ButtonExtra: | ||
| 114 | return QObject::tr("Extra"); | ||
| 105 | default: | 115 | default: |
| 106 | return QObject::tr("[undefined]"); | 116 | return QObject::tr("[undefined]"); |
| 107 | } | 117 | } |