Improved shutdown sequence in WinGLNative and GameWindow

This commit is contained in:
the_fiddler 2007-08-10 16:55:24 +00:00
parent 7e8efac81d
commit 3833030a9a
11 changed files with 113 additions and 142 deletions

View file

@ -4,6 +4,8 @@
*/ */
#endregion #endregion
#region --- Using Directives ---
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@ -13,13 +15,16 @@ using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using OpenTK;
using System.Diagnostics; using System.Diagnostics;
using System.Security; using System.Security;
using System.Security.Permissions; using System.Security.Permissions;
using System.Security.Policy; using System.Security.Policy;
using System.IO; using System.IO;
using OpenTK;
#endregion
namespace Examples namespace Examples
{ {
public partial class ExampleLauncher : Form public partial class ExampleLauncher : Form
@ -30,16 +35,18 @@ namespace Examples
[STAThread] [STAThread]
static void Main() static void Main()
{ {
StreamWriter sw = new StreamWriter(Path.Combine(System.Environment.CurrentDirectory, "debug.log")); try
System.Diagnostics.Debug.Listeners.Clear(); {
System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(sw)); if (File.Exists("debug.log"))
System.Diagnostics.Debug.AutoFlush = true; File.Delete("debug.log");
Debug.AutoFlush = true; }
System.Diagnostics.Trace.Listeners.Clear(); catch (Exception e)
System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); {
System.Diagnostics.Trace.AutoFlush = true; MessageBox.Show("Could not access debug.log");
Trace.AutoFlush = true; }
Debug.Listeners.Add(new TextWriterTraceListener("debug.log"));
try try
{ {
using (Form exampleLauncher = new ExampleLauncher()) using (Form exampleLauncher = new ExampleLauncher())
@ -54,8 +61,6 @@ namespace Examples
Debug.Close(); Debug.Close();
Trace.Flush(); Trace.Flush();
Trace.Close(); Trace.Close();
sw.Flush();
sw.Close();
} }
} }
@ -72,8 +77,9 @@ namespace Examples
Assembly.GetExecutingAssembly().GetType( Assembly.GetExecutingAssembly().GetType(
"Examples." + listBox1.SelectedItem.ToString().Replace(": ", ".").Replace(' ', '_'), "Examples." + listBox1.SelectedItem.ToString().Replace(": ", ".").Replace(' ', '_'),
true, true,
true true);
);
Debug.Print("Launching example: {0}", example.ToString());
if (example.BaseType == typeof(GameWindow)) if (example.BaseType == typeof(GameWindow))
{ {
@ -98,8 +104,7 @@ namespace Examples
expt.StackTrace, expt.StackTrace,
expt.InnerException expt.InnerException
), ),
expt.Message expt.Message);
);
} }
} }
} }
@ -112,9 +117,16 @@ namespace Examples
{ {
(ex.GetConstructor(Type.EmptyTypes).Invoke(null) as IExample).Launch(); (ex.GetConstructor(Type.EmptyTypes).Invoke(null) as IExample).Launch();
} }
catch (Exception e) catch (Exception expt)
{ {
Debug.WriteLine(e.ToString()); MessageBox.Show(
String.Format(
"Stacktrace:{0}{1}{0}{0}Inner exception:{0}{2}",
System.Environment.NewLine,
expt.StackTrace,
expt.InnerException
),
expt.Message);
} }
} }

View file

@ -13,9 +13,10 @@ using System.Data;
using System.Drawing; using System.Drawing;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using System.Diagnostics;
using OpenTK.OpenGL; using OpenTK.OpenGL;
using Enums = OpenTK.OpenGL.GL.Enums; //using Enums = OpenTK.OpenGL.GL.Enums;
using OpenTK.Platform; using OpenTK.Platform;
using System.Threading; using System.Threading;
@ -32,7 +33,7 @@ namespace Examples.WinForms
public Cube() public Cube()
{ {
InitializeComponent(); InitializeComponent();
Application.Idle += Application_Idle; Application.Idle += Application_Idle;
this.ShowDialog(); this.ShowDialog();
@ -67,7 +68,7 @@ namespace Examples.WinForms
private void Render() private void Render()
{ {
GL.MatrixMode(Enums.MatrixMode.MODELVIEW); GL.MatrixMode(GL.Enums.MatrixMode.MODELVIEW);
GL.LoadIdentity(); GL.LoadIdentity();
Glu.LookAt( Glu.LookAt(
0.0, 5.0, 5.0, 0.0, 5.0, 5.0,
@ -77,7 +78,7 @@ namespace Examples.WinForms
GL.Rotatef(angle, 0.0f, 1.0f, 0.0f); GL.Rotatef(angle, 0.0f, 1.0f, 0.0f);
angle += 0.5f; angle += 0.5f;
GL.Clear(Enums.ClearBufferMask.COLOR_BUFFER_BIT | Enums.ClearBufferMask.DEPTH_BUFFER_BIT); GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT | GL.Enums.ClearBufferMask.DEPTH_BUFFER_BIT);
DrawCube(); DrawCube();
@ -94,12 +95,12 @@ namespace Examples.WinForms
base.OnLoad(e); base.OnLoad(e);
Text = Text =
GL.GetString(Enums.StringName.VENDOR) + " " + GL.GetString(GL.Enums.StringName.VENDOR) + " " +
GL.GetString(Enums.StringName.RENDERER) + " " + GL.GetString(GL.Enums.StringName.RENDERER) + " " +
GL.GetString(Enums.StringName.VERSION); GL.GetString(GL.Enums.StringName.VERSION);
GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f); GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f);
GL.Enable(Enums.EnableCap.DEPTH_TEST); GL.Enable(GL.Enums.EnableCap.DEPTH_TEST);
glControl.KeyDown += new KeyEventHandler(Cube_KeyDown); glControl.KeyDown += new KeyEventHandler(Cube_KeyDown);
@ -126,7 +127,7 @@ namespace Examples.WinForms
//else //else
// ratio = ClientSize.Height / (double)ClientSize.Width; // ratio = ClientSize.Height / (double)ClientSize.Width;
GL.MatrixMode(Enums.MatrixMode.PROJECTION); GL.MatrixMode(GL.Enums.MatrixMode.PROJECTION);
GL.LoadIdentity(); GL.LoadIdentity();
Glu.Perspective(45.0, ratio, 1.0, 64.0); Glu.Perspective(45.0, ratio, 1.0, 64.0);
} }
@ -167,7 +168,7 @@ namespace Examples.WinForms
#region DrawCube #region DrawCube
public void DrawCube() public void DrawCube()
{ {
GL.Begin(Enums.BeginMode.QUADS); GL.Begin(GL.Enums.BeginMode.QUADS);
GL.Color3(1, 0, 0); GL.Color3(1, 0, 0);
GL.Vertex3(-1.0f, -1.0f, -1.0f); GL.Vertex3(-1.0f, -1.0f, -1.0f);
@ -218,4 +219,4 @@ namespace Examples.WinForms
#endregion #endregion
} }
} }

View file

@ -64,7 +64,7 @@ namespace OpenTK
Environment.OSVersion.Platform == (PlatformID)128) Environment.OSVersion.Platform == (PlatformID)128)
// some older versions of Mono reported 128. // some older versions of Mono reported 128.
{ {
glControl = new OpenTK.Platform.X11.X11GLControl(this, new DisplayMode(Width, Height)); glControl = new OpenTK.Platform.X11.X11GLControl(this, new DisplayMode(Width, Height));
} }
else else
{ {
@ -241,42 +241,5 @@ namespace OpenTK
#endregion #endregion
#endregion #endregion
#region --- IResizable Members ---
//public new event ResizeEvent Resize;
#endregion
#region --- IDisposable Members ---
protected override void DestroyHandle()
{
base.DestroyHandle();
glControl.Dispose();
}
/*
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manuallyCalled)
{
if (manuallyCalled)
{
glWindow.Dispose();
}
}
~GLControl()
{
this.Dispose(false);
}
*/
#endregion
} }
} }

View file

@ -55,14 +55,16 @@ namespace OpenTK
glWindow.Resize += new ResizeEvent(glWindow_Resize); glWindow.Resize += new ResizeEvent(glWindow_Resize);
glWindow.Create += new CreateEvent(glWindow_CreateInputDriver); glWindow.Create += new CreateEvent(glWindow_CreateInputDriver);
//glWindow.Destroy += new DestroyEvent(glWindow_Destroy); glWindow.Destroy += new DestroyEvent(glWindow_Destroy);
} }
void glWindow_Destroy(object sender, EventArgs e) void glWindow_Destroy(object sender, EventArgs e)
{ {
Debug.Print("GameWindow {0} notified of destruction.", this.isExiting.ToString()); Debug.Print("GameWindow destruction imminent.");
this.isExiting = true; this.isExiting = true;
this.OnDestroy(EventArgs.Empty);
glWindow.Destroy -= glWindow_Destroy; glWindow.Destroy -= glWindow_Destroy;
this.Dispose();
} }
void glWindow_CreateInputDriver(object sender, EventArgs e) void glWindow_CreateInputDriver(object sender, EventArgs e)
@ -91,7 +93,7 @@ namespace OpenTK
{ {
get get
{ {
if (driver == null) if (driver == null && !this.IsExiting)
{ {
Debug.WriteLine("WARNING: Accessed null InputDriver - creating new. This may indicate a prorgamming error."); Debug.WriteLine("WARNING: Accessed null InputDriver - creating new. This may indicate a prorgamming error.");
driver = new InputDriver(this.WindowInfo); driver = new InputDriver(this.WindowInfo);
@ -136,23 +138,6 @@ namespace OpenTK
#endregion #endregion
#region public bool Quit
/// <summary>
/// Gets a value indicating whether the current GameWindow is quitting.
/// </summary>
/// <remarks>
/// You should not call OnRenderFrame, Resize, and other GameWindow related function
/// when the quit sequence has been initiated, as indicated by the Quitting property.
/// NullReference- or ApplicationExceptions may occur otherwise.
/// </remarks>
public bool Quit
{
get { return glWindow.Quit; }
}
#endregion
#region public bool Fullscreen #region public bool Fullscreen
public bool Fullscreen public bool Fullscreen
@ -173,14 +158,14 @@ namespace OpenTK
{ {
get get
{ {
if (!glWindow.Exists) if (!this.Exists && !this.IsExiting)
{ {
Debug.WriteLine("WARNING: OpenGL Context accessed before creating a render window. This may indicate a programming error. Force-creating a render window."); Debug.WriteLine("WARNING: OpenGL Context accessed before creating a render window. This may indicate a programming error. Force-creating a render window.");
mode = new DisplayMode(640, 480); mode = new DisplayMode(640, 480);
this.CreateWindow(mode); this.CreateWindow(mode);
} }
return glWindow.Context; return glWindow.Context;
} }
} }
#endregion #endregion
@ -192,7 +177,7 @@ namespace OpenTK
/// </summary> /// </summary>
public bool Exists public bool Exists
{ {
get { return glWindow.Exists; } get { return glWindow == null ? false : glWindow.Exists; }
} }
#endregion #endregion
@ -209,7 +194,8 @@ namespace OpenTK
#region public void CreateWindow(DisplayMode mode) #region public void CreateWindow(DisplayMode mode)
/// <summary> /// <summary>
/// Creates a new render window. /// Creates a new render window. The Create event is raised after the window creation
/// is complete, to allow resource initalisation.
/// </summary> /// </summary>
/// <param name="mode">The DisplayMode of the render window.</param> /// <param name="mode">The DisplayMode of the render window.</param>
/// <exception cref="ApplicationException">Occurs when a render window already exists.</exception> /// <exception cref="ApplicationException">Occurs when a render window already exists.</exception>
@ -231,6 +217,10 @@ namespace OpenTK
public event CreateEvent Create; public event CreateEvent Create;
/// <summary>
/// Raises the Create event. Override in derived classes to initialize resources.
/// </summary>
/// <param name="e"></param>
public virtual void OnCreate(EventArgs e) public virtual void OnCreate(EventArgs e)
{ {
if (this.Create != null) if (this.Create != null)
@ -243,6 +233,10 @@ namespace OpenTK
#region public void DestroyWindow() #region public void DestroyWindow()
/// <summary>
/// Destroys the GameWindow. The Destroy event is raised before destruction commences
/// (while the opengl context still exists), to allow resource cleanup.
/// </summary>
public void DestroyWindow() public void DestroyWindow()
{ {
if (Exists) if (Exists)
@ -259,6 +253,11 @@ namespace OpenTK
#region OnDestroy #region OnDestroy
/// <summary>
/// Raises the Destroy event. Override in derived classes, to modify the shutdown
/// sequence (e.g. to release resources before shutdown).
/// </summary>
/// <param name="e"></param>
public virtual void OnDestroy(EventArgs e) public virtual void OnDestroy(EventArgs e)
{ {
if (this.Destroy != null) if (this.Destroy != null)
@ -301,7 +300,7 @@ namespace OpenTK
Debug.Print("Entering main loop"); Debug.Print("Entering main loop");
while (!this.Quit && !IsExiting) while (this.Exists && !IsExiting)
{ {
this.ProcessEvents(); this.ProcessEvents();
if (!IsExiting) if (!IsExiting)
@ -311,10 +310,10 @@ namespace OpenTK
} }
} }
if (glWindow.Exists) if (this.Exists)
{ {
glWindow.Exit(); glWindow.DestroyWindow();
while (glWindow.Exists) while (this.Exists)
{ {
this.ProcessEvents(); this.ProcessEvents();
} }
@ -356,7 +355,7 @@ namespace OpenTK
/// </remarks> /// </remarks>
public virtual void OnRenderFrame(EventArgs e) public virtual void OnRenderFrame(EventArgs e)
{ {
if (!this.Exists) if (!this.Exists && !this.IsExiting)
{ {
Debug.Print("WARNING: RenderFrame event raised, without a valid render window. This may indicate a programming error. Creating render window."); Debug.Print("WARNING: RenderFrame event raised, without a valid render window. This may indicate a programming error. Creating render window.");
mode = new DisplayMode(640, 480); mode = new DisplayMode(640, 480);
@ -384,7 +383,7 @@ namespace OpenTK
/// </remarks> /// </remarks>
public virtual void OnUpdateFrame(EventArgs e) public virtual void OnUpdateFrame(EventArgs e)
{ {
if (!this.Exists) if (!this.Exists && !this.IsExiting)
{ {
Debug.Print("WARNING: UpdateFrame event raised, without a valid render window. This may indicate a programming error. Creating render window."); Debug.Print("WARNING: UpdateFrame event raised, without a valid render window. This may indicate a programming error. Creating render window.");
mode = new DisplayMode(640, 480); mode = new DisplayMode(640, 480);

View file

@ -17,6 +17,8 @@ namespace OpenTK
{ {
IInputDriver inputDriver; IInputDriver inputDriver;
#region --- Constructors ---
public InputDriver(IWindowInfo parent) public InputDriver(IWindowInfo parent)
{ {
if (Environment.OSVersion.Version.Major > 5 || if (Environment.OSVersion.Version.Major > 5 ||
@ -35,6 +37,8 @@ namespace OpenTK
"Input handling is not supported on the current platform. Please report the problem to http://opentk.sourceforge.net"); "Input handling is not supported on the current platform. Please report the problem to http://opentk.sourceforge.net");
} }
} }
#endregion
#region --- IInputDriver Members --- #region --- IInputDriver Members ---

View file

@ -17,6 +17,7 @@ namespace OpenTK.Platform
void OnRenderFrame(EventArgs e); void OnRenderFrame(EventArgs e);
void OnUpdateFrame(EventArgs e); void OnUpdateFrame(EventArgs e);
void OnLoad(EventArgs e); void OnLoad(EventArgs e);
void Exit();
event UpdateFrameEvent UpdateFrame; event UpdateFrameEvent UpdateFrame;
event RenderFrameEvent RenderFrame; event RenderFrameEvent RenderFrame;

View file

@ -18,13 +18,12 @@ namespace OpenTK.Platform
void CreateWindow(DisplayMode mode); void CreateWindow(DisplayMode mode);
void DestroyWindow(); void DestroyWindow();
void ProcessEvents(); void ProcessEvents();
void Exit();
void OnCreate(EventArgs e); void OnCreate(EventArgs e);
void OnDestroy(EventArgs e); void OnDestroy(EventArgs e);
bool Exists { get; } bool Exists { get; }
bool Quit { get; } //bool IsExiting { get; }
IWindowInfo WindowInfo { get; } IWindowInfo WindowInfo { get; }
event CreateEvent Create; event CreateEvent Create;

View file

@ -216,7 +216,7 @@ namespace OpenTK.Platform.Windows
public void Dispose() public void Dispose()
{ {
this.Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
@ -225,6 +225,7 @@ namespace OpenTK.Platform.Windows
if (!disposed) if (!disposed)
{ {
// Clean unmanaged resources here: // Clean unmanaged resources here:
Wgl.MakeCurrent(deviceContext, renderContext);
Wgl.DeleteContext(renderContext); Wgl.DeleteContext(renderContext);
API.ReleaseDC(windowHandle, deviceContext); API.ReleaseDC(windowHandle, deviceContext);
API.FreeLibrary(opengl32Handle); API.FreeLibrary(opengl32Handle);

View file

@ -30,7 +30,7 @@ namespace OpenTK.Platform.Windows
private bool fullscreen = false; private bool fullscreen = false;
private bool disposed; private bool disposed;
private bool quit; private bool isExiting;
private bool exists; private bool exists;
private WindowInfo window; private WindowInfo window;
@ -91,7 +91,7 @@ namespace OpenTK.Platform.Windows
return; return;
case API.Constants.WM_CLOSE: case API.Constants.WM_CLOSE:
this.Exit(); this.DestroyWindow();
return; return;
case API.Constants.WM_DESTROY: case API.Constants.WM_DESTROY:
@ -99,8 +99,8 @@ namespace OpenTK.Platform.Windows
break; break;
case API.Constants.WM_QUIT: case API.Constants.WM_QUIT:
quit = true; isExiting = true;
Debug.WriteLine("Application quit."); //Debug.WriteLine("Application quit.");
return; return;
} }
@ -111,18 +111,6 @@ namespace OpenTK.Platform.Windows
#region --- INativeGLWindow Members --- #region --- INativeGLWindow Members ---
#region public void Exit()
/// <summary>
/// Starts the teardown sequence for the current window.
/// </summary>
public void Exit()
{
DestroyWindow();
}
#endregion
#region public void ProcessEvents() #region public void ProcessEvents()
private int ret; private int ret;
@ -159,9 +147,9 @@ namespace OpenTK.Platform.Windows
#region public bool Quit #region public bool Quit
public bool Quit public bool IsExiting
{ {
get { return quit; } get { return isExiting; }
} }
#endregion #endregion
@ -295,6 +283,9 @@ namespace OpenTK.Platform.Windows
#region private void DestroyWindow() #region private void DestroyWindow()
/// <summary>
/// Starts the teardown sequence for the current window.
/// </summary>
public void DestroyWindow() public void DestroyWindow()
{ {
Debug.Print("Destroying window: {0}", window.ToString()); Debug.Print("Destroying window: {0}", window.ToString());
@ -307,6 +298,11 @@ namespace OpenTK.Platform.Windows
public void OnDestroy(EventArgs e) public void OnDestroy(EventArgs e)
{ {
if (this.Destroy != null)
{
this.Destroy(this, e);
}
if (this.Handle != IntPtr.Zero) if (this.Handle != IntPtr.Zero)
{ {
Debug.Print("Window handle {0} destroyed.", this.Handle); Debug.Print("Window handle {0} destroyed.", this.Handle);
@ -314,11 +310,6 @@ namespace OpenTK.Platform.Windows
exists = false; exists = false;
} }
API.PostQuitMessage(0); API.PostQuitMessage(0);
if (this.Destroy != null)
{
this.Destroy(this, e);
}
} }
public event DestroyEvent Destroy; public event DestroyEvent Destroy;

View file

@ -38,6 +38,7 @@ namespace OpenTK.Platform.X11
private bool disposed; private bool disposed;
private bool exists; private bool exists;
private bool isExiting;
#endregion #endregion
@ -92,7 +93,7 @@ namespace OpenTK.Platform.X11
case XEventName.DestroyNotify: case XEventName.DestroyNotify:
this.exists = false; this.exists = false;
this.OnDestroy(EventArgs.Empty); this.OnDestroy(EventArgs.Empty);
quit = true; isExiting = true;
Debug.Print("X11 window {0} destroyed.", e.DestroyWindowEvent.window); Debug.Print("X11 window {0} destroyed.", e.DestroyWindowEvent.window);
return; return;
@ -139,10 +140,9 @@ namespace OpenTK.Platform.X11
#region public bool Quit #region public bool Quit
private bool quit; public bool IsExiting
public bool Quit
{ {
get { return quit; } get { return isExiting; }
} }
#endregion #endregion
@ -247,19 +247,19 @@ namespace OpenTK.Platform.X11
window.VisualInfo = glContext.CreateVisual(); window.VisualInfo = glContext.CreateVisual();
// Create a window on this display using the visual above // Create a window on this display using the visual above
Debug.Write("Creating output window... "); Debug.Write("Creating output window... ");
XSetWindowAttributes attributes = new XSetWindowAttributes(); XSetWindowAttributes attributes = new XSetWindowAttributes();
attributes.background_pixel = IntPtr.Zero; attributes.background_pixel = IntPtr.Zero;
attributes.border_pixel = IntPtr.Zero; attributes.border_pixel = IntPtr.Zero;
attributes.colormap = API.CreateColormap(window.Display, window.RootWindow, attributes.colormap = API.CreateColormap(window.Display, window.RootWindow,
window.VisualInfo.visual, 0/*AllocNone*/); //glContext.colormap; window.VisualInfo.visual, 0/*AllocNone*/); //glContext.colormap;
attributes.event_mask = (IntPtr)(EventMask.StructureNotifyMask | attributes.event_mask = (IntPtr)(EventMask.StructureNotifyMask |
EventMask.SubstructureNotifyMask | EventMask.ExposureMask); EventMask.SubstructureNotifyMask | EventMask.ExposureMask);
uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask |
(uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel; (uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel;
window.Handle = Functions.XCreateWindow(window.Display, window.RootWindow, window.Handle = Functions.XCreateWindow(window.Display, window.RootWindow,
0, 0, mode.Width, mode.Height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/, 0, 0, mode.Width, mode.Height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/,
(int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask, (int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask,

View file

@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.3.9.5")] [assembly: AssemblyVersion("0.3.9.6")]
[assembly: AssemblyFileVersion("0.3.9.5")] [assembly: AssemblyFileVersion("0.3.9.6")]