From 29dc478e2bd6440cb58f15fedc61e1aff145b450 Mon Sep 17 00:00:00 2001 From: Jaex Date: Mon, 17 Jan 2022 09:13:58 +0300 Subject: [PATCH] fixed #4951: Added support to limit region capture/image editor fps --- ShareX.HelpersLib/FPSManager.cs | 51 ++++++++++++++----- ShareX.HelpersLib/TimerResolutionManager.cs | 12 ++++- .../Forms/RegionCaptureForm.cs | 2 +- ShareX/Program.cs | 1 + 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/ShareX.HelpersLib/FPSManager.cs b/ShareX.HelpersLib/FPSManager.cs index e9d68a7ca..63aa83793 100644 --- a/ShareX.HelpersLib/FPSManager.cs +++ b/ShareX.HelpersLib/FPSManager.cs @@ -25,45 +25,68 @@ using System; using System.Diagnostics; +using System.Threading; namespace ShareX.HelpersLib { public class FPSManager { - public event Action FPSChanged; + public event Action FPSUpdated; public int FPS { get; private set; } + public int FPSLimit { get; set; } = 100; private int frameCount; - private Stopwatch timer; + private Stopwatch fpsTimer, frameTimer; public FPSManager() { - timer = new Stopwatch(); + fpsTimer = new Stopwatch(); + frameTimer = new Stopwatch(); } - protected void OnFPSChanged() + protected void OnFPSUpdated() { - FPSChanged?.Invoke(); + FPSUpdated?.Invoke(); } public void Update() { - if (!timer.IsRunning) - { - timer.Start(); - } - frameCount++; - if (timer.ElapsedMilliseconds >= 1000) + if (!fpsTimer.IsRunning) { - FPS = (int)(frameCount / timer.Elapsed.TotalSeconds); + fpsTimer.Start(); + } + else if (fpsTimer.ElapsedMilliseconds >= 1000) + { + FPS = (int)(frameCount / fpsTimer.Elapsed.TotalSeconds); - OnFPSChanged(); + OnFPSUpdated(); frameCount = 0; - timer.Restart(); + fpsTimer.Restart(); + } + + if (FPSLimit > 0) + { + if (!frameTimer.IsRunning) + { + frameTimer.Start(); + } + else + { + double currentFrameDuration = frameTimer.Elapsed.TotalMilliseconds; + double targetFrameDuration = 1000d / FPSLimit; + + if (currentFrameDuration < targetFrameDuration) + { + int diff = (int)Math.Round(targetFrameDuration - currentFrameDuration); + Thread.Sleep(diff); + } + + frameTimer.Restart(); + } } } } diff --git a/ShareX.HelpersLib/TimerResolutionManager.cs b/ShareX.HelpersLib/TimerResolutionManager.cs index c8337fc2e..4eae7b4c9 100644 --- a/ShareX.HelpersLib/TimerResolutionManager.cs +++ b/ShareX.HelpersLib/TimerResolutionManager.cs @@ -28,13 +28,23 @@ namespace ShareX.HelpersLib { - public static class TimerResolutionManager + public class TimerResolutionManager : IDisposable { private static readonly object thisLock = new object(); private static bool enabled; private static uint lastPeriod; + public TimerResolutionManager(uint period = 1) + { + Enable(period); + } + + public void Dispose() + { + Disable(); + } + public static bool Enable(uint period = 1) { lock (thisLock) diff --git a/ShareX.ScreenCaptureLib/Forms/RegionCaptureForm.cs b/ShareX.ScreenCaptureLib/Forms/RegionCaptureForm.cs index 8a794b151..5dcefabba 100644 --- a/ShareX.ScreenCaptureLib/Forms/RegionCaptureForm.cs +++ b/ShareX.ScreenCaptureLib/Forms/RegionCaptureForm.cs @@ -109,7 +109,7 @@ public RegionCaptureForm(RegionCaptureMode mode, RegionCaptureOptions options, B Duration = TimeSpan.FromMilliseconds(200) }; fpsManager = new FPSManager(); - fpsManager.FPSChanged += FpsManager_FPSChanged; + fpsManager.FPSUpdated += FpsManager_FPSChanged; if (IsEditorMode && Options.ShowEditorPanTip) { diff --git a/ShareX/Program.cs b/ShareX/Program.cs index eb34b5013..834759b19 100644 --- a/ShareX/Program.cs +++ b/ShareX/Program.cs @@ -296,6 +296,7 @@ private static void Main(string[] args) MultiInstance = CLI.IsCommandExist("multi", "m"); using (ApplicationInstanceManager instanceManager = new ApplicationInstanceManager(!MultiInstance, args, SingleInstanceCallback)) + using (TimerResolutionManager timerResolutionManager = new TimerResolutionManager()) { Run(); }