mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-01-12 20:55:37 +00:00
Added Closing event that can be used to cancel a call to GameWindow.Exit().
Made GameWindow.Exit() thread-safe. ExitAsync() is now privateee (use Exit() instead). GameWindow.Exit() now correctly works when called from inside the OnLoad method or the Load event.
This commit is contained in:
parent
6678fe52c3
commit
8bb1a85bc1
|
@ -17,6 +17,7 @@ using OpenTK.Input;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using OpenTK.Graphics.OpenGL.Enums;
|
using OpenTK.Graphics.OpenGL.Enums;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace OpenTK
|
namespace OpenTK
|
||||||
{
|
{
|
||||||
|
@ -66,7 +67,7 @@ namespace OpenTK
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
double update_period, render_period;
|
double update_period, render_period;
|
||||||
double target_update_period, target_render_period, target_render_period_doubled;
|
double target_update_period, target_render_period;
|
||||||
// TODO: Implement these:
|
// TODO: Implement these:
|
||||||
double update_time, render_time;//, event_time;
|
double update_time, render_time;//, event_time;
|
||||||
//bool allow_sleep = true; // If true, GameWindow will call Timer.Sleep() if there is enough time.
|
//bool allow_sleep = true; // If true, GameWindow will call Timer.Sleep() if there is enough time.
|
||||||
|
@ -77,6 +78,9 @@ namespace OpenTK
|
||||||
|
|
||||||
IGraphicsContext glContext;
|
IGraphicsContext glContext;
|
||||||
|
|
||||||
|
int main_loop_thread_id;
|
||||||
|
object exit_lock = new object();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region --- Contructors ---
|
#region --- Contructors ---
|
||||||
|
@ -221,29 +225,34 @@ namespace OpenTK
|
||||||
void glWindow_Destroy(object sender, EventArgs e)
|
void glWindow_Destroy(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
glWindow.Destroy -= glWindow_Destroy;
|
glWindow.Destroy -= glWindow_Destroy;
|
||||||
this.Exit();
|
ExitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region void ExitInternal()
|
#region void ExitInternal()
|
||||||
|
|
||||||
/// <internal />
|
// Stops the main loop, if one exists.
|
||||||
/// <summary>Stops the main loop.</summary>
|
|
||||||
void ExitInternal()
|
void ExitInternal()
|
||||||
{
|
{
|
||||||
//Debug.Print("Firing GameWindowExitException");
|
|
||||||
if (HasMainLoop)
|
if (HasMainLoop)
|
||||||
{
|
{
|
||||||
throw new GameWindowExitException();
|
throw new GameWindowExitException();
|
||||||
}
|
}
|
||||||
if (CloseWindow != null)
|
|
||||||
{
|
|
||||||
CloseWindow(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public event EventHandler CloseWindow;
|
|
||||||
|
|
||||||
|
#region void ExitAsync()
|
||||||
|
|
||||||
|
// Gracefully exits the GameWindow. May be called from any thread.
|
||||||
|
void ExitAsync()
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
throw new ObjectDisposedException("GameWindow");
|
||||||
|
|
||||||
|
UpdateFrame += CallExitInternal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used in ExitAsync() to ensure ExitInternal() is called from the main thread.
|
||||||
void CallExitInternal(GameWindow sender, UpdateFrameEventArgs e)
|
void CallExitInternal(GameWindow sender, UpdateFrameEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateFrame -= CallExitInternal;
|
UpdateFrame -= CallExitInternal;
|
||||||
|
@ -252,6 +261,8 @@ namespace OpenTK
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region bool MustResize
|
#region bool MustResize
|
||||||
|
|
||||||
bool MustResize
|
bool MustResize
|
||||||
|
@ -277,45 +288,36 @@ namespace OpenTK
|
||||||
|
|
||||||
#region public virtual void Exit()
|
#region public virtual void Exit()
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gracefully exits the GameWindow. May only be called from the thread where the GameWindow was created.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Override if you want to provide yor own exit sequence.</para>
|
|
||||||
/// <para>If you override this method, place a call to base.Exit(), to ensure
|
|
||||||
/// proper OpenTK shutdown.</para>
|
|
||||||
/// </remarks>
|
|
||||||
public virtual void Exit()
|
|
||||||
{
|
|
||||||
if (disposed) throw new ObjectDisposedException("GameWindow");
|
|
||||||
//glWindow.DestroyWindow();
|
|
||||||
//while (glWindow.Exists)
|
|
||||||
// glWindow.ProcessEvents();
|
|
||||||
if (HasMainLoop)
|
|
||||||
ExitAsync();
|
|
||||||
else
|
|
||||||
ExitInternal();
|
|
||||||
//isExiting = true;
|
|
||||||
//UpdateFrame += CallExitInternal;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region public virtual void ExitAsync()
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gracefully exits the GameWindow. May be called from any thread.
|
/// Gracefully exits the GameWindow. May be called from any thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>Override if you want to provide yor own exit sequence.</para>
|
/// <para>Override if you are not using <see cref="GameWindow.Run()"/>.</para>
|
||||||
/// <para>If you override this method, place a call to base.ExitAsync(), to ensure
|
/// <para>If you override this method, place a call to base.Exit(), to ensure proper OpenTK shutdown.</para>
|
||||||
/// proper OpenTK shutdown.</para>
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public virtual void ExitAsync()
|
public virtual void Exit()
|
||||||
{
|
{
|
||||||
//isExiting = true;
|
lock (exit_lock)
|
||||||
if (disposed) throw new ObjectDisposedException("GameWindow");
|
{
|
||||||
UpdateFrame += CallExitInternal;
|
if (disposed)
|
||||||
|
throw new ObjectDisposedException("GameWindow");
|
||||||
|
|
||||||
|
if (!IsExiting && Exists)
|
||||||
|
{
|
||||||
|
CancelEventArgs e = new CancelEventArgs();
|
||||||
|
Closing(this, e);
|
||||||
|
if (e.Cancel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HasMainLoop)
|
||||||
|
{
|
||||||
|
if (main_loop_thread_id == Thread.CurrentThread.ManagedThreadId)
|
||||||
|
ExitInternal();
|
||||||
|
else
|
||||||
|
ExitAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -427,25 +429,6 @@ namespace OpenTK
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#if false
|
|
||||||
|
|
||||||
#region public IInputDriver InputDriver
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an interface to the InputDriver used to obtain Keyboard, Mouse and Joystick input.
|
|
||||||
/// </summary>
|
|
||||||
public IInputDriver InputDriver
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#region public void Run()
|
#region public void Run()
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -484,13 +467,21 @@ namespace OpenTK
|
||||||
/// <param name="frames_per_second">The frequency of RenderFrame events.</param>
|
/// <param name="frames_per_second">The frequency of RenderFrame events.</param>
|
||||||
public void Run(double updates_per_second, double frames_per_second)
|
public void Run(double updates_per_second, double frames_per_second)
|
||||||
{
|
{
|
||||||
if (disposed) throw new ObjectDisposedException("GameWindow");
|
if (disposed)
|
||||||
|
throw new ObjectDisposedException("GameWindow");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Necessary to be here, otherwise Exit() wouldn't work correctly when called inside OnLoad().
|
||||||
|
hasMainLoop = true;
|
||||||
|
main_loop_thread_id = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
|
||||||
if (updates_per_second < 0.0 || updates_per_second > 200.0)
|
if (updates_per_second < 0.0 || updates_per_second > 200.0)
|
||||||
throw new ArgumentOutOfRangeException("updates_per_second", updates_per_second, "Parameter should be inside the range [0.0, 200.0]");
|
throw new ArgumentOutOfRangeException("updates_per_second", updates_per_second,
|
||||||
|
"Parameter should be inside the range [0.0, 200.0]");
|
||||||
if (frames_per_second < 0.0 || frames_per_second > 200.0)
|
if (frames_per_second < 0.0 || frames_per_second > 200.0)
|
||||||
throw new ArgumentOutOfRangeException("frames_per_second", frames_per_second, "Parameter should be inside the range [0.0, 200.0]");
|
throw new ArgumentOutOfRangeException("frames_per_second", frames_per_second,
|
||||||
|
"Parameter should be inside the range [0.0, 200.0]");
|
||||||
|
|
||||||
TargetUpdateFrequency = updates_per_second;
|
TargetUpdateFrequency = updates_per_second;
|
||||||
TargetRenderFrequency = frames_per_second;
|
TargetRenderFrequency = frames_per_second;
|
||||||
|
@ -520,21 +511,12 @@ namespace OpenTK
|
||||||
//sleep_granularity = System.Math.Round(1000.0 * update_watch.Elapsed.TotalSeconds / test_times, MidpointRounding.AwayFromZero) / 1000.0;
|
//sleep_granularity = System.Math.Round(1000.0 * update_watch.Elapsed.TotalSeconds / test_times, MidpointRounding.AwayFromZero) / 1000.0;
|
||||||
//update_watch.Reset(); // We don't want to affect the first UpdateFrame!
|
//update_watch.Reset(); // We don't want to affect the first UpdateFrame!
|
||||||
|
|
||||||
try
|
OnLoadInternal(EventArgs.Empty);
|
||||||
{
|
|
||||||
OnLoadInternal(EventArgs.Empty);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.WriteLine(String.Format("OnLoad failed: {0}", e.ToString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug.Print("Elevating priority.");
|
//Debug.Print("Elevating priority.");
|
||||||
//Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
|
//Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
|
||||||
|
|
||||||
Debug.Print("Entering main loop.");
|
Debug.Print("Entering main loop.");
|
||||||
hasMainLoop = true;
|
|
||||||
while (!isExiting)
|
while (!isExiting)
|
||||||
{
|
{
|
||||||
ProcessEvents();
|
ProcessEvents();
|
||||||
|
@ -966,6 +948,15 @@ namespace OpenTK
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region --- Events ---
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the GameWindow is about to close.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<CancelEventArgs> Closing = delegate(object sender, CancelEventArgs e) { };
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region --- GameWindow Timing ---
|
#region --- GameWindow Timing ---
|
||||||
|
|
||||||
// TODO: Disabled because it is not reliable enough. Use vsync as a workaround.
|
// TODO: Disabled because it is not reliable enough. Use vsync as a workaround.
|
||||||
|
@ -1000,12 +991,11 @@ namespace OpenTK
|
||||||
if (disposed) throw new ObjectDisposedException("GameWindow");
|
if (disposed) throw new ObjectDisposedException("GameWindow");
|
||||||
if (value <= 0.005)
|
if (value <= 0.005)
|
||||||
{
|
{
|
||||||
target_render_period = target_render_period_doubled = 0.0;
|
target_render_period = 0.0;
|
||||||
}
|
}
|
||||||
else if (value <= 1.0)
|
else if (value <= 1.0)
|
||||||
{
|
{
|
||||||
target_render_period = value;
|
target_render_period = value;
|
||||||
target_render_period_doubled = 2.0 * target_render_period;
|
|
||||||
}
|
}
|
||||||
else Debug.Print("Target render period clamped to 1.0 seconds.");
|
else Debug.Print("Target render period clamped to 1.0 seconds.");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue