From 3833030a9a5ff403af9460429233481ea147e7d6 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Fri, 10 Aug 2007 16:55:24 +0000 Subject: [PATCH] Improved shutdown sequence in WinGLNative and GameWindow --- Source/Examples/ExampleLauncher.cs | 48 ++++++++----- Source/Examples/WinForms/Cube.cs | 23 +++--- Source/OpenTK/GLControl.cs | 39 +--------- Source/OpenTK/GameWindow.cs | 71 +++++++++---------- Source/OpenTK/InputDriver.cs | 4 ++ Source/OpenTK/Platform/IGameWindow.cs | 1 + Source/OpenTK/Platform/INativeGLWindow.cs | 3 +- .../OpenTK/Platform/Windows/WinGLContext.cs | 3 +- Source/OpenTK/Platform/Windows/WinGLNative.cs | 37 ++++------ Source/OpenTK/Platform/X11/X11GLNative.cs | 22 +++--- Source/OpenTK/Properties/AssemblyInfo.cs | 4 +- 11 files changed, 113 insertions(+), 142 deletions(-) diff --git a/Source/Examples/ExampleLauncher.cs b/Source/Examples/ExampleLauncher.cs index aeebc664..78107f64 100644 --- a/Source/Examples/ExampleLauncher.cs +++ b/Source/Examples/ExampleLauncher.cs @@ -4,6 +4,8 @@ */ #endregion +#region --- Using Directives --- + using System; using System.Collections.Generic; using System.ComponentModel; @@ -13,13 +15,16 @@ using System.Text; using System.Windows.Forms; using System.Reflection; using System.Threading; -using OpenTK; using System.Diagnostics; using System.Security; using System.Security.Permissions; using System.Security.Policy; using System.IO; +using OpenTK; + +#endregion + namespace Examples { public partial class ExampleLauncher : Form @@ -30,16 +35,18 @@ namespace Examples [STAThread] static void Main() { - StreamWriter sw = new StreamWriter(Path.Combine(System.Environment.CurrentDirectory, "debug.log")); - System.Diagnostics.Debug.Listeners.Clear(); - System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(sw)); - System.Diagnostics.Debug.AutoFlush = true; - Debug.AutoFlush = true; - System.Diagnostics.Trace.Listeners.Clear(); - System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); - System.Diagnostics.Trace.AutoFlush = true; - Trace.AutoFlush = true; + try + { + if (File.Exists("debug.log")) + File.Delete("debug.log"); + } + catch (Exception e) + { + MessageBox.Show("Could not access debug.log"); + } + Debug.Listeners.Add(new TextWriterTraceListener("debug.log")); + try { using (Form exampleLauncher = new ExampleLauncher()) @@ -54,8 +61,6 @@ namespace Examples Debug.Close(); Trace.Flush(); Trace.Close(); - sw.Flush(); - sw.Close(); } } @@ -72,8 +77,9 @@ namespace Examples Assembly.GetExecutingAssembly().GetType( "Examples." + listBox1.SelectedItem.ToString().Replace(": ", ".").Replace(' ', '_'), true, - true - ); + true); + + Debug.Print("Launching example: {0}", example.ToString()); if (example.BaseType == typeof(GameWindow)) { @@ -98,8 +104,7 @@ namespace Examples expt.StackTrace, expt.InnerException ), - expt.Message - ); + expt.Message); } } } @@ -112,9 +117,16 @@ namespace Examples { (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); } } diff --git a/Source/Examples/WinForms/Cube.cs b/Source/Examples/WinForms/Cube.cs index 8ab04589..6384ff1f 100644 --- a/Source/Examples/WinForms/Cube.cs +++ b/Source/Examples/WinForms/Cube.cs @@ -13,9 +13,10 @@ using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; +using System.Diagnostics; using OpenTK.OpenGL; -using Enums = OpenTK.OpenGL.GL.Enums; +//using Enums = OpenTK.OpenGL.GL.Enums; using OpenTK.Platform; using System.Threading; @@ -32,7 +33,7 @@ namespace Examples.WinForms public Cube() { InitializeComponent(); - + Application.Idle += Application_Idle; this.ShowDialog(); @@ -67,7 +68,7 @@ namespace Examples.WinForms private void Render() { - GL.MatrixMode(Enums.MatrixMode.MODELVIEW); + GL.MatrixMode(GL.Enums.MatrixMode.MODELVIEW); GL.LoadIdentity(); Glu.LookAt( 0.0, 5.0, 5.0, @@ -77,7 +78,7 @@ namespace Examples.WinForms GL.Rotatef(angle, 0.0f, 1.0f, 0.0f); 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(); @@ -94,12 +95,12 @@ namespace Examples.WinForms base.OnLoad(e); Text = - GL.GetString(Enums.StringName.VENDOR) + " " + - GL.GetString(Enums.StringName.RENDERER) + " " + - GL.GetString(Enums.StringName.VERSION); + GL.GetString(GL.Enums.StringName.VENDOR) + " " + + GL.GetString(GL.Enums.StringName.RENDERER) + " " + + GL.GetString(GL.Enums.StringName.VERSION); 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); @@ -126,7 +127,7 @@ namespace Examples.WinForms //else // ratio = ClientSize.Height / (double)ClientSize.Width; - GL.MatrixMode(Enums.MatrixMode.PROJECTION); + GL.MatrixMode(GL.Enums.MatrixMode.PROJECTION); GL.LoadIdentity(); Glu.Perspective(45.0, ratio, 1.0, 64.0); } @@ -167,7 +168,7 @@ namespace Examples.WinForms #region DrawCube public void DrawCube() { - GL.Begin(Enums.BeginMode.QUADS); + GL.Begin(GL.Enums.BeginMode.QUADS); GL.Color3(1, 0, 0); GL.Vertex3(-1.0f, -1.0f, -1.0f); @@ -218,4 +219,4 @@ namespace Examples.WinForms #endregion } -} \ No newline at end of file +} diff --git a/Source/OpenTK/GLControl.cs b/Source/OpenTK/GLControl.cs index 95ed6c5d..b7a040b9 100644 --- a/Source/OpenTK/GLControl.cs +++ b/Source/OpenTK/GLControl.cs @@ -64,7 +64,7 @@ namespace OpenTK Environment.OSVersion.Platform == (PlatformID)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 { @@ -241,42 +241,5 @@ namespace OpenTK #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 } } diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs index 26ff5c20..5b1d224a 100644 --- a/Source/OpenTK/GameWindow.cs +++ b/Source/OpenTK/GameWindow.cs @@ -55,14 +55,16 @@ namespace OpenTK glWindow.Resize += new ResizeEvent(glWindow_Resize); 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) { - Debug.Print("GameWindow {0} notified of destruction.", this.isExiting.ToString()); + Debug.Print("GameWindow destruction imminent."); this.isExiting = true; + this.OnDestroy(EventArgs.Empty); glWindow.Destroy -= glWindow_Destroy; + this.Dispose(); } void glWindow_CreateInputDriver(object sender, EventArgs e) @@ -91,7 +93,7 @@ namespace OpenTK { get { - if (driver == null) + if (driver == null && !this.IsExiting) { Debug.WriteLine("WARNING: Accessed null InputDriver - creating new. This may indicate a prorgamming error."); driver = new InputDriver(this.WindowInfo); @@ -136,23 +138,6 @@ namespace OpenTK #endregion - #region public bool Quit - - /// - /// Gets a value indicating whether the current GameWindow is quitting. - /// - /// - /// 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. - /// - public bool Quit - { - get { return glWindow.Quit; } - } - - #endregion - #region public bool Fullscreen public bool Fullscreen @@ -173,14 +158,14 @@ namespace OpenTK { get { - if (!glWindow.Exists) - { - 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); - this.CreateWindow(mode); - } - return glWindow.Context; - } + 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."); + mode = new DisplayMode(640, 480); + this.CreateWindow(mode); + } + return glWindow.Context; + } } #endregion @@ -192,7 +177,7 @@ namespace OpenTK /// public bool Exists { - get { return glWindow.Exists; } + get { return glWindow == null ? false : glWindow.Exists; } } #endregion @@ -209,7 +194,8 @@ namespace OpenTK #region public void CreateWindow(DisplayMode mode) /// - /// 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. /// /// The DisplayMode of the render window. /// Occurs when a render window already exists. @@ -231,6 +217,10 @@ namespace OpenTK public event CreateEvent Create; + /// + /// Raises the Create event. Override in derived classes to initialize resources. + /// + /// public virtual void OnCreate(EventArgs e) { if (this.Create != null) @@ -243,6 +233,10 @@ namespace OpenTK #region public void DestroyWindow() + /// + /// Destroys the GameWindow. The Destroy event is raised before destruction commences + /// (while the opengl context still exists), to allow resource cleanup. + /// public void DestroyWindow() { if (Exists) @@ -259,6 +253,11 @@ namespace OpenTK #region OnDestroy + /// + /// Raises the Destroy event. Override in derived classes, to modify the shutdown + /// sequence (e.g. to release resources before shutdown). + /// + /// public virtual void OnDestroy(EventArgs e) { if (this.Destroy != null) @@ -301,7 +300,7 @@ namespace OpenTK Debug.Print("Entering main loop"); - while (!this.Quit && !IsExiting) + while (this.Exists && !IsExiting) { this.ProcessEvents(); if (!IsExiting) @@ -311,10 +310,10 @@ namespace OpenTK } } - if (glWindow.Exists) + if (this.Exists) { - glWindow.Exit(); - while (glWindow.Exists) + glWindow.DestroyWindow(); + while (this.Exists) { this.ProcessEvents(); } @@ -356,7 +355,7 @@ namespace OpenTK /// 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."); mode = new DisplayMode(640, 480); @@ -384,7 +383,7 @@ namespace OpenTK /// 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."); mode = new DisplayMode(640, 480); diff --git a/Source/OpenTK/InputDriver.cs b/Source/OpenTK/InputDriver.cs index dfcdfb25..1ed3dc0b 100644 --- a/Source/OpenTK/InputDriver.cs +++ b/Source/OpenTK/InputDriver.cs @@ -17,6 +17,8 @@ namespace OpenTK { IInputDriver inputDriver; + #region --- Constructors --- + public InputDriver(IWindowInfo parent) { 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"); } } + + #endregion #region --- IInputDriver Members --- diff --git a/Source/OpenTK/Platform/IGameWindow.cs b/Source/OpenTK/Platform/IGameWindow.cs index 0eca79b9..b7166a8e 100644 --- a/Source/OpenTK/Platform/IGameWindow.cs +++ b/Source/OpenTK/Platform/IGameWindow.cs @@ -17,6 +17,7 @@ namespace OpenTK.Platform void OnRenderFrame(EventArgs e); void OnUpdateFrame(EventArgs e); void OnLoad(EventArgs e); + void Exit(); event UpdateFrameEvent UpdateFrame; event RenderFrameEvent RenderFrame; diff --git a/Source/OpenTK/Platform/INativeGLWindow.cs b/Source/OpenTK/Platform/INativeGLWindow.cs index d916f81a..873565fd 100644 --- a/Source/OpenTK/Platform/INativeGLWindow.cs +++ b/Source/OpenTK/Platform/INativeGLWindow.cs @@ -18,13 +18,12 @@ namespace OpenTK.Platform void CreateWindow(DisplayMode mode); void DestroyWindow(); void ProcessEvents(); - void Exit(); void OnCreate(EventArgs e); void OnDestroy(EventArgs e); bool Exists { get; } - bool Quit { get; } + //bool IsExiting { get; } IWindowInfo WindowInfo { get; } event CreateEvent Create; diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 4945b90d..5b8a2c5a 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -216,7 +216,7 @@ namespace OpenTK.Platform.Windows public void Dispose() { - this.Dispose(true); + Dispose(true); GC.SuppressFinalize(this); } @@ -225,6 +225,7 @@ namespace OpenTK.Platform.Windows if (!disposed) { // Clean unmanaged resources here: + Wgl.MakeCurrent(deviceContext, renderContext); Wgl.DeleteContext(renderContext); API.ReleaseDC(windowHandle, deviceContext); API.FreeLibrary(opengl32Handle); diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index b59f5e4a..d6731bc9 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -30,7 +30,7 @@ namespace OpenTK.Platform.Windows private bool fullscreen = false; private bool disposed; - private bool quit; + private bool isExiting; private bool exists; private WindowInfo window; @@ -91,7 +91,7 @@ namespace OpenTK.Platform.Windows return; case API.Constants.WM_CLOSE: - this.Exit(); + this.DestroyWindow(); return; case API.Constants.WM_DESTROY: @@ -99,8 +99,8 @@ namespace OpenTK.Platform.Windows break; case API.Constants.WM_QUIT: - quit = true; - Debug.WriteLine("Application quit."); + isExiting = true; + //Debug.WriteLine("Application quit."); return; } @@ -111,18 +111,6 @@ namespace OpenTK.Platform.Windows #region --- INativeGLWindow Members --- - #region public void Exit() - - /// - /// Starts the teardown sequence for the current window. - /// - public void Exit() - { - DestroyWindow(); - } - - #endregion - #region public void ProcessEvents() private int ret; @@ -159,9 +147,9 @@ namespace OpenTK.Platform.Windows #region public bool Quit - public bool Quit + public bool IsExiting { - get { return quit; } + get { return isExiting; } } #endregion @@ -295,6 +283,9 @@ namespace OpenTK.Platform.Windows #region private void DestroyWindow() + /// + /// Starts the teardown sequence for the current window. + /// public void DestroyWindow() { Debug.Print("Destroying window: {0}", window.ToString()); @@ -307,6 +298,11 @@ namespace OpenTK.Platform.Windows public void OnDestroy(EventArgs e) { + if (this.Destroy != null) + { + this.Destroy(this, e); + } + if (this.Handle != IntPtr.Zero) { Debug.Print("Window handle {0} destroyed.", this.Handle); @@ -314,11 +310,6 @@ namespace OpenTK.Platform.Windows exists = false; } API.PostQuitMessage(0); - - if (this.Destroy != null) - { - this.Destroy(this, e); - } } public event DestroyEvent Destroy; diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 09a3a6eb..c711edd1 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -38,6 +38,7 @@ namespace OpenTK.Platform.X11 private bool disposed; private bool exists; + private bool isExiting; #endregion @@ -92,7 +93,7 @@ namespace OpenTK.Platform.X11 case XEventName.DestroyNotify: this.exists = false; this.OnDestroy(EventArgs.Empty); - quit = true; + isExiting = true; Debug.Print("X11 window {0} destroyed.", e.DestroyWindowEvent.window); return; @@ -139,10 +140,9 @@ namespace OpenTK.Platform.X11 #region public bool Quit - private bool quit; - public bool Quit + public bool IsExiting { - get { return quit; } + get { return isExiting; } } #endregion @@ -247,19 +247,19 @@ namespace OpenTK.Platform.X11 window.VisualInfo = glContext.CreateVisual(); // Create a window on this display using the visual above - Debug.Write("Creating output window... "); - - XSetWindowAttributes attributes = new XSetWindowAttributes(); - attributes.background_pixel = IntPtr.Zero; + Debug.Write("Creating output window... "); + + XSetWindowAttributes attributes = new XSetWindowAttributes(); + attributes.background_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; attributes.event_mask = (IntPtr)(EventMask.StructureNotifyMask | 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; - + window.Handle = Functions.XCreateWindow(window.Display, window.RootWindow, 0, 0, mode.Width, mode.Height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/, (int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask, diff --git a/Source/OpenTK/Properties/AssemblyInfo.cs b/Source/OpenTK/Properties/AssemblyInfo.cs index af176828..a35870cc 100644 --- a/Source/OpenTK/Properties/AssemblyInfo.cs +++ b/Source/OpenTK/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.3.9.5")] -[assembly: AssemblyFileVersion("0.3.9.5")] +[assembly: AssemblyVersion("0.3.9.6")] +[assembly: AssemblyFileVersion("0.3.9.6")]