summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/fiber.cpp5
-rw-r--r--src/common/input.h7
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/hid/emulated_console.cpp2
-rw-r--r--src/core/hid/emulated_controller.cpp2
-rw-r--r--src/core/hle/kernel/k_process.cpp6
-rw-r--r--src/core/hle/kernel/k_process.h6
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp2
-rw-r--r--src/core/hle/kernel/k_thread.cpp78
-rw-r--r--src/core/hle/kernel/k_thread.h11
-rw-r--r--src/core/hle/kernel/k_worker_task.h18
-rw-r--r--src/core/hle/kernel/k_worker_task_manager.cpp42
-rw-r--r--src/core/hle/kernel/k_worker_task_manager.h33
-rw-r--r--src/core/hle/kernel/kernel.cpp11
-rw-r--r--src/core/hle/kernel/kernel.h7
-rw-r--r--src/input_common/drivers/mouse.cpp35
-rw-r--r--src/input_common/drivers/mouse.h2
-rw-r--r--src/input_common/input_engine.cpp2
-rw-r--r--src/input_common/input_mapping.cpp13
-rw-r--r--src/video_core/host_shaders/astc_decoder.comp80
-rw-r--r--src/yuzu/configuration/config.cpp11
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp10
-rw-r--r--src/yuzu/uisettings.h9
23 files changed, 312 insertions, 83 deletions
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/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
152void KProcess::DoWorkerTaskImpl() {
153 UNIMPLEMENTED();
154}
155
152KResourceLimit* KProcess::GetResourceLimit() const { 156KResourceLimit* 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
65class KProcess final 66class 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
69public: 69public:
@@ -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
338bool KThread::IsSignaled() const { 339bool 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
382void 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
397void KThread::DoWorkerTaskImpl() {
398 // Finish the termination that was begun by Exit().
399 this->FinishTermination();
400}
401
384void KThread::Pin(s32 current_core) { 402void 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
700void KThread::WaitCancel() { 701void 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
727void KThread::Suspend() { 728void 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
739void KThread::Continue() { 743void 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
103class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, 104class 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
9namespace Kernel {
10
11class KWorkerTask : public KSynchronizationObject {
12public:
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
12namespace Kernel {
13
14KWorkerTask::KWorkerTask(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
15
16void 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
27KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "yuzu:KWorkerTaskManager") {}
28
29void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) {
30 ASSERT(type <= WorkerType::Count);
31 kernel.WorkerTaskManager().AddTask(kernel, task);
32}
33
34void 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
10namespace Kernel {
11
12class KernelCore;
13class KWorkerTask;
14
15class KWorkerTaskManager final {
16public:
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
26private:
27 void AddTask(KernelCore& kernel, KWorkerTask* task);
28
29private:
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..e5cf9abb3 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"
@@ -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
1143KWorkerTaskManager& KernelCore::WorkerTaskManager() {
1144 return impl->worker_task_manager;
1145}
1146
1147const KWorkerTaskManager& KernelCore::WorkerTaskManager() const {
1148 return impl->worker_task_manager;
1149}
1150
1140bool KernelCore::IsPhantomModeForSingleCore() const { 1151bool 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;
52class KSharedMemoryInfo; 52class KSharedMemoryInfo;
53class KThread; 53class KThread;
54class KTransferMemory; 54class KTransferMemory;
55class KWorkerTaskManager;
55class KWritableEvent; 56class KWritableEvent;
56class KCodeMemory; 57class KCodeMemory;
57class PhysicalCore; 58class 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
346private: 353private:
347 friend class KProcess; 354 friend class KProcess;
348 friend class KThread; 355 friend class KThread;
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;
16constexpr int mouse_axis_y = 1; 16constexpr int mouse_axis_y = 1;
17constexpr int wheel_axis_x = 2; 17constexpr int wheel_axis_x = 2;
18constexpr int wheel_axis_y = 3; 18constexpr int wheel_axis_y = 3;
19constexpr int motion_wheel_y = 4;
19constexpr int touch_axis_x = 10; 20constexpr int touch_axis_x = 10;
20constexpr int touch_axis_y = 11; 21constexpr int touch_axis_y = 11;
21constexpr PadIdentifier identifier = { 22constexpr 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
141void Mouse::ReleaseAllButtons() { 146void Mouse::ReleaseAllButtons() {
@@ -171,13 +176,39 @@ AnalogMapping Mouse::GetAnalogMappingForDevice(
171 return mapping; 176 return mapping;
172} 177}
173 178
179Common::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
174Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) const { 202Common::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/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/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.
157uint Replicate(uint val, uint num_bits, uint to_bit) { 157uint 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
190uint FastReplicateTo8(uint value, uint num_bits) { 187uint 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
232uint FastReplicateTo8(uint value, uint num_bits) {
233 return FastReplicate(value, num_bits, 8);
210} 234}
211 235
212uint FastReplicateTo6(uint value, uint num_bits) { 236uint 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
228uint Div3Floor(uint v) { 240uint Div3Floor(uint v) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 99a7397fc..33d50667a 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -743,7 +743,10 @@ void Config::ReadUIValues() {
743 qt_config->beginGroup(QStringLiteral("UI")); 743 qt_config->beginGroup(QStringLiteral("UI"));
744 744
745 UISettings::values.theme = 745 UISettings::values.theme =
746 ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second)) 746 ReadSetting(
747 QStringLiteral("theme"),
748 QString::fromUtf8(
749 UISettings::themes[static_cast<size_t>(UISettings::Theme::DarkColorful)].second))
747 .toString(); 750 .toString();
748 ReadBasicSetting(UISettings::values.enable_discord_presence); 751 ReadBasicSetting(UISettings::values.enable_discord_presence);
749 ReadBasicSetting(UISettings::values.select_user_on_boot); 752 ReadBasicSetting(UISettings::values.select_user_on_boot);
@@ -1270,8 +1273,10 @@ void Config::SaveSystemValues() {
1270void Config::SaveUIValues() { 1273void Config::SaveUIValues() {
1271 qt_config->beginGroup(QStringLiteral("UI")); 1274 qt_config->beginGroup(QStringLiteral("UI"));
1272 1275
1273 WriteSetting(QStringLiteral("theme"), UISettings::values.theme, 1276 WriteSetting(
1274 QString::fromUtf8(UISettings::themes[0].second)); 1277 QStringLiteral("theme"), UISettings::values.theme,
1278 QString::fromUtf8(
1279 UISettings::themes[static_cast<size_t>(UISettings::Theme::DarkColorful)].second));
1275 WriteBasicSetting(UISettings::values.enable_discord_presence); 1280 WriteBasicSetting(UISettings::values.enable_discord_presence);
1276 WriteBasicSetting(UISettings::values.select_user_on_boot); 1281 WriteBasicSetting(UISettings::values.select_user_on_boot);
1277 1282
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 }
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 402c4556d..f7298ddad 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -29,6 +29,15 @@ struct Shortcut {
29 ContextualShortcut shortcut; 29 ContextualShortcut shortcut;
30}; 30};
31 31
32enum class Theme {
33 Default,
34 DefaultColorful,
35 Dark,
36 DarkColorful,
37 MidnightBlue,
38 MidnightBlueColorful,
39};
40
32using Themes = std::array<std::pair<const char*, const char*>, 6>; 41using Themes = std::array<std::pair<const char*, const char*>, 6>;
33extern const Themes themes; 42extern const Themes themes;
34 43