diff options
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.h | 5 |
2 files changed, 30 insertions, 17 deletions
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 5574269eb..9b382bf56 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -38,20 +38,16 @@ void NVFlinger::SplitVSync(std::stop_token stop_token) { | |||
| 38 | 38 | ||
| 39 | Common::SetCurrentThreadName(name.c_str()); | 39 | Common::SetCurrentThreadName(name.c_str()); |
| 40 | Common::SetCurrentThreadPriority(Common::ThreadPriority::High); | 40 | Common::SetCurrentThreadPriority(Common::ThreadPriority::High); |
| 41 | s64 delay = 0; | 41 | |
| 42 | while (!stop_token.stop_requested()) { | 42 | while (!stop_token.stop_requested()) { |
| 43 | vsync_signal.wait(false); | ||
| 44 | vsync_signal.store(false); | ||
| 45 | |||
| 43 | guard->lock(); | 46 | guard->lock(); |
| 44 | const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count(); | 47 | |
| 45 | Compose(); | 48 | Compose(); |
| 46 | const auto ticks = GetNextTicks(); | 49 | |
| 47 | const s64 time_end = system.CoreTiming().GetGlobalTimeNs().count(); | ||
| 48 | const s64 time_passed = time_end - time_start; | ||
| 49 | const s64 next_time = std::max<s64>(0, ticks - time_passed - delay); | ||
| 50 | guard->unlock(); | 50 | guard->unlock(); |
| 51 | if (next_time > 0) { | ||
| 52 | std::this_thread::sleep_for(std::chrono::nanoseconds{next_time}); | ||
| 53 | } | ||
| 54 | delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time; | ||
| 55 | } | 51 | } |
| 56 | } | 52 | } |
| 57 | 53 | ||
| @@ -66,27 +62,41 @@ NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_dr | |||
| 66 | guard = std::make_shared<std::mutex>(); | 62 | guard = std::make_shared<std::mutex>(); |
| 67 | 63 | ||
| 68 | // Schedule the screen composition events | 64 | // Schedule the screen composition events |
| 69 | composition_event = Core::Timing::CreateEvent( | 65 | multi_composition_event = Core::Timing::CreateEvent( |
| 66 | "ScreenComposition", | ||
| 67 | [this](std::uintptr_t, s64 time, | ||
| 68 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 69 | vsync_signal.store(true); | ||
| 70 | vsync_signal.notify_all(); | ||
| 71 | return std::chrono::nanoseconds(GetNextTicks()); | ||
| 72 | }); | ||
| 73 | |||
| 74 | single_composition_event = Core::Timing::CreateEvent( | ||
| 70 | "ScreenComposition", | 75 | "ScreenComposition", |
| 71 | [this](std::uintptr_t, s64 time, | 76 | [this](std::uintptr_t, s64 time, |
| 72 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | 77 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { |
| 73 | const auto lock_guard = Lock(); | 78 | const auto lock_guard = Lock(); |
| 74 | Compose(); | 79 | Compose(); |
| 75 | 80 | ||
| 76 | return std::max(std::chrono::nanoseconds::zero(), | 81 | return std::chrono::nanoseconds(GetNextTicks()); |
| 77 | std::chrono::nanoseconds(GetNextTicks()) - ns_late); | ||
| 78 | }); | 82 | }); |
| 79 | 83 | ||
| 80 | if (system.IsMulticore()) { | 84 | if (system.IsMulticore()) { |
| 85 | system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event); | ||
| 81 | vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); | 86 | vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); |
| 82 | } else { | 87 | } else { |
| 83 | system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, composition_event); | 88 | system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event); |
| 84 | } | 89 | } |
| 85 | } | 90 | } |
| 86 | 91 | ||
| 87 | NVFlinger::~NVFlinger() { | 92 | NVFlinger::~NVFlinger() { |
| 88 | if (!system.IsMulticore()) { | 93 | if (system.IsMulticore()) { |
| 89 | system.CoreTiming().UnscheduleEvent(composition_event, 0); | 94 | system.CoreTiming().UnscheduleEvent(multi_composition_event, {}); |
| 95 | vsync_thread.request_stop(); | ||
| 96 | vsync_signal.store(true); | ||
| 97 | vsync_signal.notify_all(); | ||
| 98 | } else { | ||
| 99 | system.CoreTiming().UnscheduleEvent(single_composition_event, {}); | ||
| 90 | } | 100 | } |
| 91 | 101 | ||
| 92 | for (auto& display : displays) { | 102 | for (auto& display : displays) { |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 4775597cc..044ac6ac8 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -126,12 +126,15 @@ private: | |||
| 126 | u32 swap_interval = 1; | 126 | u32 swap_interval = 1; |
| 127 | 127 | ||
| 128 | /// Event that handles screen composition. | 128 | /// Event that handles screen composition. |
| 129 | std::shared_ptr<Core::Timing::EventType> composition_event; | 129 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; |
| 130 | std::shared_ptr<Core::Timing::EventType> single_composition_event; | ||
| 130 | 131 | ||
| 131 | std::shared_ptr<std::mutex> guard; | 132 | std::shared_ptr<std::mutex> guard; |
| 132 | 133 | ||
| 133 | Core::System& system; | 134 | Core::System& system; |
| 134 | 135 | ||
| 136 | std::atomic<bool> vsync_signal; | ||
| 137 | |||
| 135 | std::jthread vsync_thread; | 138 | std::jthread vsync_thread; |
| 136 | 139 | ||
| 137 | KernelHelpers::ServiceContext service_context; | 140 | KernelHelpers::ServiceContext service_context; |