Skip to content

Commit

Permalink
Change screen refresh from infinite loop to 60hz timer
Browse files Browse the repository at this point in the history
  • Loading branch information
JorisVanEijden committed Jan 23, 2024
1 parent b5ca25b commit 838863e
Showing 1 changed file with 21 additions and 34 deletions.
55 changes: 21 additions & 34 deletions src/Spice86/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@
using Spice86.Models.Debugging;
using Spice86.Shared.Emulator.Video;

using Timer = System.Timers.Timer;

/// <inheritdoc cref="Spice86.Shared.Interfaces.IGui" />
public sealed partial class MainWindowViewModel : ViewModelBase, IPauseStatus, IGui, IDisposable {
private const double ScreenRefreshHz = 60;
private readonly ILoggerService _loggerService;
private readonly IUIDispatcherTimer _uiDispatcherTimer;
private readonly IHostStorageProvider _hostStorageProvider;
Expand All @@ -58,10 +61,9 @@ public sealed partial class MainWindowViewModel : ViewModelBase, IPauseStatus, I
private bool _isAppClosing;

private static Action? _uiUpdateMethod;
private bool _exitDrawThread;
private Action? _drawAction;
private Thread? _drawThread;
private SemaphoreSlim? _drawingSemaphoreSlim;
private readonly Timer _drawTimer = new(1000.0 / ScreenRefreshHz);
private readonly SemaphoreSlim? _drawingSemaphoreSlim = new(1, 1);

public event EventHandler<KeyboardEventArgs>? KeyUp;
public event EventHandler<KeyboardEventArgs>? KeyDown;
Expand Down Expand Up @@ -138,12 +140,6 @@ public double Scale {

private bool _isDrawThreadInitialized;

private void DrawThreadMethod() {
while (!_exitDrawThread) {
_drawAction?.Invoke();
}
}

[ObservableProperty]
private Cursor? _cursor = Cursor.Default;

Expand Down Expand Up @@ -339,31 +335,24 @@ public void ShowColorPalette() {
public void ResetTimeMultiplier() => TimeMultiplier = Configuration.TimeMultiplier;

private void InitializeRenderingThread() {
if (_disposed || _isSettingResolution || _isAppClosing || _uiUpdateMethod is null || Bitmap is null || RenderScreen is null) {
if (_isDrawThreadInitialized || _disposed || _isSettingResolution || _isAppClosing || _uiUpdateMethod is null || Bitmap is null || RenderScreen is null) {
return;
}
if (!_isDrawThreadInitialized) {
_drawThread = new Thread(DrawThreadMethod) {
Name = "UIRenderThread"
};
_drawingSemaphoreSlim = new(1, 1);
_drawThread.Start();
_isDrawThreadInitialized = true;
}

_drawAction ??= () => {
unsafe {
_drawingSemaphoreSlim?.Wait();
try {
using ILockedFramebuffer pixels = Bitmap.Lock();
var uiRenderEventArgs = new UIRenderEventArgs(pixels.Address, pixels.RowBytes * pixels.Size.Height / 4);
RenderScreen.Invoke(this, uiRenderEventArgs);
} finally {
_drawingSemaphoreSlim?.Release();
}
_uiDispatcher.Post(static () => _uiUpdateMethod.Invoke(), DispatcherPriority.Render);
_drawAction = () => {
_drawingSemaphoreSlim?.Wait();
try {
using ILockedFramebuffer pixels = Bitmap.Lock();
var uiRenderEventArgs = new UIRenderEventArgs(pixels.Address, pixels.RowBytes * pixels.Size.Height / 4);
RenderScreen.Invoke(this, uiRenderEventArgs);
} finally {
_drawingSemaphoreSlim?.Release();
}
_uiDispatcher.Post(static () => _uiUpdateMethod.Invoke(), DispatcherPriority.Render);
};

_drawTimer.Elapsed += (_, _) => _drawAction.Invoke();
_drawTimer.Start();
_isDrawThreadInitialized = true;
}

public double MouseX { get; set; }
Expand Down Expand Up @@ -487,10 +476,8 @@ private void Dispose(bool disposing) {

private void DisposeDrawThread() {
_drawAction = null;
_exitDrawThread = true;
if (_drawThread?.IsAlive == true) {
_drawThread.Join();
}
_drawTimer.Stop();
_drawTimer.Dispose();
_isDrawThreadInitialized = false;
}

Expand Down

0 comments on commit 838863e

Please sign in to comment.