From 63608b1dd73bbfb2001e1bbf94687311ca5e3950 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Wed, 26 Mar 2008 19:43:57 +0000 Subject: [PATCH] Updates to GameWindow shutdown and X11 locking behavior. --- Source/OpenTK/GameWindow.cs | 169 +++++++++++------- Source/OpenTK/Graphics/GraphicsContext.cs | 51 +++--- Source/OpenTK/Platform/X11/API.cs | 4 +- Source/OpenTK/Platform/X11/Functions.cs | 38 +++- Source/OpenTK/Platform/X11/X11GLContext.cs | 82 +++++---- Source/OpenTK/Platform/X11/X11GLNative.cs | 125 +++++++------ Source/OpenTK/Platform/X11/X11GraphicsMode.cs | 51 ++++-- 7 files changed, 324 insertions(+), 196 deletions(-) diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs index 1b690c0c..de49c4ca 100644 --- a/Source/OpenTK/GameWindow.cs +++ b/Source/OpenTK/GameWindow.cs @@ -275,7 +275,8 @@ namespace OpenTK /// proper OpenTK shutdown. /// public virtual void Exit() - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); //glWindow.DestroyWindow(); //while (glWindow.Exists) // glWindow.ProcessEvents(); @@ -301,7 +302,8 @@ namespace OpenTK /// public virtual void ExitAsync() { - //isExiting = true; + //isExiting = true; + if (disposed) throw new ObjectDisposedException("GameWindow"); UpdateFrame += CallExitInternal; } @@ -315,7 +317,7 @@ namespace OpenTK /// public bool IsIdle { - get { return glWindow.IsIdle; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.IsIdle; } } #endregion @@ -328,8 +330,8 @@ namespace OpenTK /// public bool Fullscreen { - get { return glWindow.Fullscreen; } - set { glWindow.Fullscreen = value; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.Fullscreen; } + set { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Fullscreen = value; } } #endregion @@ -337,12 +339,15 @@ namespace OpenTK #region public IGraphicsContext Context /// - /// Returns the opengl IGLontext associated with the current GameWindow. - /// Forces window creation. + /// Returns the opengl IGraphicsContext associated with the current GameWindow. /// public IGraphicsContext Context { - get { return glContext; } + get + { + if (disposed) throw new ObjectDisposedException("GameWindow"); + return glContext; + } } #endregion @@ -367,11 +372,13 @@ namespace OpenTK public string Title { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.Title; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Title = value; } } @@ -404,7 +411,7 @@ namespace OpenTK public IWindowInfo WindowInfo { - get { return glWindow.WindowInfo; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.WindowInfo; } } #endregion @@ -436,7 +443,8 @@ namespace OpenTK /// (while the opengl context still exists), to allow resource cleanup. /// public void DestroyWindow() - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (Exists) glWindow.DestroyWindow(); else @@ -452,7 +460,8 @@ namespace OpenTK /// /// public void Run() - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); Run(0.0, 0.0); } @@ -462,7 +471,8 @@ namespace OpenTK /// /// public void Run(double updateFrequency) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); Run(updateFrequency, 0.0); } @@ -472,7 +482,8 @@ namespace OpenTK /// The frequency of UpdateFrame events. /// The frequency of RenderFrame events. public void Run(double updates_per_second, double frames_per_second) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); try { if (updates_per_second < 0.0 || updates_per_second > 200.0) @@ -617,8 +628,9 @@ namespace OpenTK if (Exists) { - glContext.Dispose(); - glWindow.DestroyWindow(); + glContext.Dispose(); + glContext = null; + glWindow.DestroyWindow(); } while (this.Exists) this.ProcessEvents(); @@ -641,7 +653,8 @@ namespace OpenTK /// /// public void ProcessEvents() - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (!isExiting) glWindow.InputDriver.Poll(); glWindow.ProcessEvents(); @@ -663,7 +676,7 @@ namespace OpenTK /// /// private void OnRenderFrameInternal(RenderFrameEventArgs e) - { + { if (RenderFrame != null) RenderFrame(this, e); @@ -679,7 +692,8 @@ namespace OpenTK /// The base implementation (base.OnRenderFrame) is empty, there is no need to call it. /// public virtual void OnRenderFrame(RenderFrameEventArgs e) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); } /// @@ -717,7 +731,8 @@ namespace OpenTK /// The base implementation (base.OnUpdateFrame) is empty, there is no need to call it. /// public virtual void OnUpdateFrame(UpdateFrameEventArgs e) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); } /// @@ -767,7 +782,8 @@ namespace OpenTK /// /// Not used. public virtual void OnLoad(EventArgs e) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); } #endregion @@ -799,7 +815,8 @@ namespace OpenTK /// /// Not used. public virtual void OnUnload(EventArgs e) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); } #endregion @@ -814,7 +831,7 @@ namespace OpenTK /// public bool IsExiting { - get { return isExiting; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return isExiting; } } #endregion @@ -827,7 +844,8 @@ namespace OpenTK public KeyboardDevice Keyboard { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); //if (input_driver.Keyboard.Count > 0) // return input_driver.Keyboard[0]; //else @@ -850,7 +868,8 @@ namespace OpenTK public MouseDevice Mouse { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); //if (input_driver.Mouse.Count > 0) // return input_driver.Mouse[0]; //else @@ -873,11 +892,13 @@ namespace OpenTK public VSyncMode VSync { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); return vsync; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value == VSyncMode.Off) Context.VSync = false; else @@ -897,7 +918,8 @@ namespace OpenTK /// /// Calling this function is equivalent to calling Context.SwapBuffers() public void SwapBuffers() - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); this.Context.SwapBuffers(); } @@ -930,11 +952,13 @@ namespace OpenTK public double TargetRenderPeriod { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); return target_render_period; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value <= 0.005) { target_render_period = target_render_period_doubled = 0.0; @@ -962,13 +986,15 @@ namespace OpenTK public double TargetRenderFrequency { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (TargetRenderPeriod == 0.0) return 0.0; return 1.0 / TargetRenderPeriod; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value < 1.0) { TargetRenderPeriod = 0.0; @@ -995,11 +1021,13 @@ namespace OpenTK public double TargetUpdatePeriod { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); return target_update_period; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value <= 0.005) { target_update_period = 0.0; @@ -1026,13 +1054,15 @@ namespace OpenTK public double TargetUpdateFrequency { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (TargetUpdatePeriod == 0.0) return 0.0; return 1.0 / TargetUpdatePeriod; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value < 1.0) { TargetUpdatePeriod = 0.0; @@ -1055,7 +1085,8 @@ namespace OpenTK public double RenderFrequency { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (render_period == 0.0) return 1.0; return 1.0 / render_period; @@ -1072,7 +1103,8 @@ namespace OpenTK public double RenderPeriod { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); return render_period; } } @@ -1087,7 +1119,8 @@ namespace OpenTK public double UpdateFrequency { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (update_period == 0.0) return 1.0; return 1.0 / update_period; @@ -1104,7 +1137,8 @@ namespace OpenTK public double UpdatePeriod { get - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); return update_period; } } @@ -1118,8 +1152,8 @@ namespace OpenTK /// public double RenderTime { - get { return render_time; } - protected set { render_time = value; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return render_time; } + protected set { if (disposed) throw new ObjectDisposedException("GameWindow"); render_time = value; } } #endregion @@ -1131,7 +1165,7 @@ namespace OpenTK /// public double UpdateTime { - get { return update_time; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return update_time; } } #endregion @@ -1147,9 +1181,10 @@ namespace OpenTK /// public int Width { - get { return width; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return width; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value == this.Width) { return; @@ -1174,9 +1209,10 @@ namespace OpenTK /// public int Height { - get { return height; } + get { if (disposed) throw new ObjectDisposedException("GameWindow"); return height; } set - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); if (value == this.Height) { return; @@ -1205,8 +1241,8 @@ namespace OpenTK /// public event ResizeEvent Resize { - add { glWindow.Resize += value; } - remove { glWindow.Resize -= value; } + add { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Resize += value; } + remove { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Resize -= value; } } /// @@ -1231,7 +1267,8 @@ namespace OpenTK /// /// Contains information about the Resize event. protected virtual void OnResize(ResizeEventArgs e) - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); } #endregion @@ -1303,21 +1340,14 @@ namespace OpenTK #endif #region --- IDisposable Members --- - /// - /// Not used yet. - /// - private void DisposeInternal() - { - Dispose(); // User overridable Dispose method. - Dispose(true); - GC.SuppressFinalize(this); - } - /// /// Disposes of the GameWindow, releasing all resources consumed by it. /// public virtual void Dispose() - { + { + if (disposed) throw new ObjectDisposedException("GameWindow"); + Dispose(true); + GC.SuppressFinalize(this); } private void Dispose(bool manual) @@ -1326,8 +1356,11 @@ namespace OpenTK { if (manual) { - if (glContext != null) - glContext.Dispose(); + if (glContext != null) + { + glContext.Dispose(); + glContext = null; + } if (glWindow != null) { @@ -1340,10 +1373,10 @@ namespace OpenTK } /// Finalizes unmanaged resources consumed by the GameWindow. - ~GameWindow() - { - Dispose(false); - } + //~GameWindow() + //{ + // Dispose(false); + //} #endregion } diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs index c601a736..81cb7fa6 100644 --- a/Source/OpenTK/Graphics/GraphicsContext.cs +++ b/Source/OpenTK/Graphics/GraphicsContext.cs @@ -83,8 +83,11 @@ namespace OpenTK.Graphics implementation = new OpenTK.Platform.X11.X11GLContext(mode, window, shareContext, DirectRendering); else throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); - - available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this)); + + lock (context_lock) + { + available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this)); + } //(implementation as IGraphicsContextInternal).LoadAll(); } @@ -118,14 +121,17 @@ namespace OpenTK.Graphics public static GraphicsContext CurrentContext { get - { - if (available_contexts.Count > 0) + { + lock (context_lock) { - ContextHandle handle = GetCurrentContext(); - if (handle.Handle != IntPtr.Zero) - return (GraphicsContext)available_contexts[handle].Target; + if (available_contexts.Count > 0) + { + ContextHandle handle = GetCurrentContext(); + if (handle.Handle != IntPtr.Zero) + return (GraphicsContext)available_contexts[handle].Target; + } + return null; } - return null; } //set //{ @@ -199,8 +205,11 @@ namespace OpenTK.Graphics void CreateContext(bool direct, IGraphicsContext source) { this.Destroy += ContextDestroyed; - - available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this)); + + lock (context_lock) + { + available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this)); + } //OpenTK.Graphics.OpenGL.GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit); //if (StaticGetCurrentContext == null) @@ -363,13 +372,15 @@ namespace OpenTK.Graphics void Dispose(bool manual) { if (!disposed) - { + { + Debug.WriteLine("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString()); + lock (context_lock) + { + available_contexts.Remove((this as IGraphicsContextInternal).Context); + } + if (manual) { - Debug.WriteLine("Disposing context."); - available_contexts.Remove((this as IGraphicsContextInternal).Context); - - // TODO: Check if this is safe if (implementation != null) implementation.Dispose(); } @@ -377,10 +388,10 @@ namespace OpenTK.Graphics } } - ~GraphicsContext() - { - this.Dispose(false); - } + //~GraphicsContext() + //{ + // this.Dispose(false); + //} #endregion } @@ -398,4 +409,4 @@ namespace OpenTK.Graphics } #endregion -} \ No newline at end of file +} diff --git a/Source/OpenTK/Platform/X11/API.cs b/Source/OpenTK/Platform/X11/API.cs index 66da0f21..003284b1 100644 --- a/Source/OpenTK/Platform/X11/API.cs +++ b/Source/OpenTK/Platform/X11/API.cs @@ -66,7 +66,9 @@ namespace OpenTK.Platform.X11 #endregion static API() - { + { + Debug.Print("Initializing threaded X11: {0}.", Functions.XInitThreads().ToString()); + AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); // Bad idea - Windows.Forms will steal our events! diff --git a/Source/OpenTK/Platform/X11/Functions.cs b/Source/OpenTK/Platform/X11/Functions.cs index 0e23e3f3..565925c0 100644 --- a/Source/OpenTK/Platform/X11/Functions.cs +++ b/Source/OpenTK/Platform/X11/Functions.cs @@ -40,6 +40,35 @@ namespace OpenTK.Platform.X11 using Status = System.Int32; using SizeID = System.UInt16; + #endregion + + #region DisplayLock + + /* + internal class DisplayLock : IDisposable + { + IntPtr display; + + public DisplayLock(IntPtr display) + { + if (display == IntPtr.Zero) throw new ArgumentException("display", "Must be a valid X11 display connection."); + this.display = display; + Functions.XLockDisplay(display); + } + + publc void Dispose() + { + Functions.XUnlockDisplay(display); + GC.SuppressFinalize(this); + } + + ~DisplayLock() + { + Functions.XUnlockDisplay(display); + } + } + */ + #endregion internal static partial class Functions @@ -382,7 +411,12 @@ namespace OpenTK.Platform.X11 } [DllImport("libX11")] - public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc); - + public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc); + + [DllImport("libX11")] + public static extern void XLockDisplay(Display display); + + [DllImport("libX11")] + public static extern void XUnlockDisplay(Display display); } } diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index d2a31791..134e22f0 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -63,13 +63,18 @@ namespace OpenTK.Platform.X11 XVisualInfo info = new XVisualInfo(); info.visualid = (IntPtr)mode.Index; info.screen = currentWindow.Screen; - int items; - IntPtr vs = Functions.XGetVisualInfo(currentWindow.Display, XVisualInfoMask.ID | XVisualInfoMask.Screen, ref info, out items); - if (items == 0) - throw new GraphicsModeException(String.Format("Invalid GraphicsMode specified ({0}).", mode)); + int items; + + lock (API.Lock) + { + IntPtr vs = Functions.XGetVisualInfo(currentWindow.Display, XVisualInfoMask.ID | XVisualInfoMask.Screen, ref info, out items); + if (items == 0) + throw new GraphicsModeException(String.Format("Invalid GraphicsMode specified ({0}).", mode)); + + info = (XVisualInfo)Marshal.PtrToStructure(vs, typeof(XVisualInfo)); + Functions.XFree(vs); + } - info = (XVisualInfo)Marshal.PtrToStructure(vs, typeof(XVisualInfo)); - Functions.XFree(vs); return info; } @@ -88,26 +93,29 @@ namespace OpenTK.Platform.X11 Debug.Write(direct ? "direct, " : "indirect, "); Debug.Write(shareHandle.Handle == IntPtr.Zero ? "not shared... " : String.Format("shared with ({0})... ", shareHandle)); + + lock (API.Lock) + { + XVisualInfo info = window.VisualInfo; // Cannot pass a Property by reference. + context = Glx.CreateContext(window.Display, ref info, shareHandle.Handle, direct); - XVisualInfo info = window.VisualInfo; // Cannot pass a Property by reference. - context = Glx.CreateContext(window.Display, ref info, shareHandle.Handle, direct); + // Context creation succeeded, return. + if (context != IntPtr.Zero) + { + Debug.Print("done! (id: {0})", context); + return; + } - // Context creation succeeded, return. - if (context != IntPtr.Zero) - { - Debug.Print("done! (id: {0})", context); - return; - } - - // Context creation failed. Retry with a non-shared context with the direct/indirect bit flipped. - Debug.Print("failed."); - Debug.Write(String.Format("Creating OpenGL context: {0}, not shared... ", !direct ? "direct" : "indirect")); - context = Glx.CreateContext(window.Display, ref info, IntPtr.Zero, !direct); - if (context != IntPtr.Zero) - { - Debug.Print("done! (id: {0})", context); - return; - } + // Context creation failed. Retry with a non-shared context with the direct/indirect bit flipped. + Debug.Print("failed."); + Debug.Write(String.Format("Creating OpenGL context: {0}, not shared... ", !direct ? "direct" : "indirect")); + context = Glx.CreateContext(window.Display, ref info, IntPtr.Zero, !direct); + if (context != IntPtr.Zero) + { + Debug.Print("done! (id: {0})", context); + return; + } + } Debug.Print("failed."); throw new GraphicsModeException("Failed to create OpenGL context. Glx.CreateContext call returned 0."); @@ -194,10 +202,10 @@ namespace OpenTK.Platform.X11 set { if (vsync_supported) - { + { int error_code = Glx.Sgi.SwapInterval(value ? 1 : 0); if (error_code != 0) - throw new GraphicsException(String.Format("Could not set vsync, error code: {0}", error_code)); + throw new GraphicsException(String.Format("Could not set vsync, error code: {0}", error_code)); vsync_interval = value ? 1 : 0; } } @@ -286,7 +294,7 @@ namespace OpenTK.Platform.X11 #region static ContextHandle GetCurrentContext() static ContextHandle GetCurrentContext() - { + { return (ContextHandle)Glx.GetCurrentContext(); } @@ -305,16 +313,22 @@ namespace OpenTK.Platform.X11 private void Dispose(bool manuallyCalled) { if (!disposed) - { + { // Clean unmanaged resources: - - Glx.MakeCurrent(currentWindow.Display, IntPtr.Zero, IntPtr.Zero); - Glx.DestroyContext(currentWindow.Display, context); - //API.Free(visual); - + try + { + Functions.XLockDisplay(currentWindow.Display); + Glx.MakeCurrent(currentWindow.Display, IntPtr.Zero, IntPtr.Zero); + Glx.DestroyContext(currentWindow.Display, context); + //Functions.XFree(visual); + } + finally + { + Functions.XUnlockDisplay(currentWindow.Display); + } + if (manuallyCalled) { - // Safe to clean managed resources, too } } disposed = true; diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index a4a465b6..6e5628e8 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -94,12 +94,22 @@ namespace OpenTK.Platform.X11 //window.Screen = (int)xplatui.GetField("ScreenNo", // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); - // Open a display connection to the X server, and obtain the screen and root window. - window.Display = API.DefaultDisplay;//Functions.XOpenDisplay(IntPtr.Zero); // IntPtr.Zero == default display + // Open a display connection to the X server, and obtain the screen and root window. + window.Display = API.DefaultDisplay;//Functions.XOpenDisplay(IntPtr.Zero); // IntPtr.Zero == default display if (window.Display == IntPtr.Zero) throw new Exception("Could not open connection to X"); - window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; - window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); // API.RootWindow; + + try + { + Functions.XLockDisplay(window.Display); + window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; + window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); // API.RootWindow; + } + finally + { + Functions.XUnlockDisplay(window.Display); + } + Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen, window.RootWindow); RegisterAtoms(window); @@ -144,57 +154,61 @@ namespace OpenTK.Platform.X11 if (width <= 0) throw new ArgumentOutOfRangeException("width", "Must be higher than zero."); if (height <= 0) throw new ArgumentOutOfRangeException("height", "Must be higher than zero."); if (exists) throw new InvalidOperationException("A render window already exists."); + + XVisualInfo info = new XVisualInfo(); - Debug.Indent(); + Debug.Indent(); + + lock (API.Lock) + { + info.visualid = mode.Index; + int dummy; + window.VisualInfo = (XVisualInfo)Marshal.PtrToStructure( + Functions.XGetVisualInfo(window.Display, XVisualInfoMask.ID, ref info, out dummy), typeof(XVisualInfo)); - XVisualInfo info = new XVisualInfo(); - info.visualid = mode.Index; - int dummy; - window.VisualInfo = (XVisualInfo)Marshal.PtrToStructure( - Functions.XGetVisualInfo(window.Display, XVisualInfoMask.ID, ref info, out dummy), typeof(XVisualInfo)); + // Create a window on this display using the visual above + Debug.Write("Opening render window... "); - // Create a window on this display using the visual above - Debug.Write("Opening render window... "); + XSetWindowAttributes attributes = new XSetWindowAttributes(); + attributes.background_pixel = IntPtr.Zero; + attributes.border_pixel = IntPtr.Zero; + attributes.colormap = Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/); + window.EventMask = EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | + EventMask.KeyReleaseMask | EventMask.KeyPressMask | + EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask | + EventMask.ButtonPressMask | EventMask.ButtonReleaseMask; + attributes.event_mask = (IntPtr)window.EventMask; - XSetWindowAttributes attributes = new XSetWindowAttributes(); - attributes.background_pixel = IntPtr.Zero; - attributes.border_pixel = IntPtr.Zero; - attributes.colormap = Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/); - window.EventMask = EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | - EventMask.KeyReleaseMask | EventMask.KeyPressMask | - EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask | - EventMask.ButtonPressMask | EventMask.ButtonReleaseMask; - attributes.event_mask = (IntPtr)window.EventMask; + uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | + (uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel; - uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | - (uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel; + window.WindowHandle = Functions.XCreateWindow(window.Display, window.RootWindow, + 0, 0, width, height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/, + (int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask, ref attributes); - window.WindowHandle = Functions.XCreateWindow(window.Display, window.RootWindow, - 0, 0, width, height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/, - (int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask, ref attributes); - - if (window.WindowHandle == IntPtr.Zero) - throw new ApplicationException("XCreateWindow call failed (returned 0)."); - - //XVisualInfo vis = window.VisualInfo; - //Glx.CreateContext(window.Display, ref vis, IntPtr.Zero, true); + if (window.WindowHandle == IntPtr.Zero) + throw new ApplicationException("XCreateWindow call failed (returned 0)."); + //XVisualInfo vis = window.VisualInfo; + //Glx.CreateContext(window.Display, ref vis, IntPtr.Zero, true); + } context = new GraphicsContext(mode, window); - + // Set the window hints XSizeHints hints = new XSizeHints(); hints.x = 0; hints.y = 0; hints.width = width; hints.height = height; - hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition); - Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints); - - // Register for window destroy notification - IntPtr wm_destroy_atom = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true); - //XWMHints hint = new XWMHints(); - Functions.XSetWMProtocols(window.Display, window.WindowHandle, new IntPtr[] { wm_destroy_atom }, 1); + hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition); + lock (API.Lock) + { + Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints); + // Register for window destroy notification + IntPtr wm_destroy_atom = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true); + Functions.XSetWMProtocols(window.Display, window.WindowHandle, new IntPtr[] { wm_destroy_atom }, 1); + } Top = Left = 0; Right = Width; Bottom = Height; @@ -206,10 +220,11 @@ namespace OpenTK.Platform.X11 //Functions.XSetWMProperties(display, window, name, name, 0, /*None*/ null, 0, hints); Debug.Print("done! (id: {0})", window.WindowHandle); - - //(glContext as IGLContextCreationHack).SetWindowHandle(window.Handle); - - API.MapRaised(window.Display, window.WindowHandle); + + lock (API.Lock) + { + API.MapRaised(window.Display, window.WindowHandle); + } mapped = true; //context.CreateContext(true, null); @@ -663,18 +678,24 @@ namespace OpenTK.Platform.X11 private void Dispose(bool manuallyCalled) { if (!disposed) - { - if (window != null) + { + if (window != null && window.WindowHandle != IntPtr.Zero) { - if (window.WindowHandle != IntPtr.Zero) - Functions.XDestroyWindow(window.Display, window.WindowHandle); - //if (window.Display != IntPtr.Zero) - // Functions.XCloseDisplay(window.Display); + try + { + Functions.XLockDisplay(window.Display); + Functions.XDestroyWindow(window.Display, window.WindowHandle); + } + finally + { + Functions.XUnlockDisplay(window.Display); + } + window = null; } - + if (manuallyCalled) - { + { } disposed = true; } diff --git a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs index d51bfa72..86864c91 100644 --- a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs +++ b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs @@ -80,9 +80,12 @@ namespace OpenTK.Platform.X11 visualAttributes.Add((int)0); // Select a visual that matches the parameters set by the user. - lock (API.Lock) - { - IntPtr display = API.DefaultDisplay; //Functions.XOpenDisplay(IntPtr.Zero); + IntPtr display = API.DefaultDisplay; //Functions.XOpenDisplay(IntPtr.Zero); + + try + { + Functions.XLockDisplay(display); + int screen = Functions.XDefaultScreen(display); IntPtr root = Functions.XRootWindow(display, screen); Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root); @@ -112,24 +115,26 @@ namespace OpenTK.Platform.X11 ++buffers; // the above lines returns 0 - false and 1 - true. int st; Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st); - stereo = st != 0; - + stereo = st != 0; + gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples, - new ColorFormat(ar, ag, ab, aa), buffers, stereo); - - //Functions.XCloseDisplay(display); + new ColorFormat(ar, ag, ab, aa), buffers, stereo); + } + finally + { + Functions.XUnlockDisplay(display); } // Prepare Windows.Forms for creating OpenGL drawables. - lock (API.Lock) - { - Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); - IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); - IntPtr root = (IntPtr)xplatui.GetField("RootWindow", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); - int screen = (int)xplatui.GetField("ScreenNo", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + //lock (API.Lock) + //{ + // Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); + // IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", + // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + // IntPtr root = (IntPtr)xplatui.GetField("RootWindow", + // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + // int screen = (int)xplatui.GetField("ScreenNo", + // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); //xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) @@ -137,9 +142,17 @@ namespace OpenTK.Platform.X11 //xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) // .SetValue(null, Functions.XCreateColormap(display, root, visual, 0)); - } + //} - Functions.XFree(visual); + try + { + Functions.XLockDisplay(display); + Functions.XFree(visual); + } + finally + { + Functions.XUnlockDisplay(display); + } return gfx; }