Updates to GameWindow shutdown and X11 locking behavior.

This commit is contained in:
the_fiddler 2008-03-26 19:43:57 +00:00
parent 560f132764
commit 63608b1dd7
7 changed files with 324 additions and 196 deletions

View file

@ -275,7 +275,8 @@ namespace OpenTK
/// proper OpenTK shutdown.</para> /// proper OpenTK shutdown.</para>
/// </remarks> /// </remarks>
public virtual void Exit() public virtual void Exit()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
//glWindow.DestroyWindow(); //glWindow.DestroyWindow();
//while (glWindow.Exists) //while (glWindow.Exists)
// glWindow.ProcessEvents(); // glWindow.ProcessEvents();
@ -301,7 +302,8 @@ namespace OpenTK
/// </remarks> /// </remarks>
public virtual void ExitAsync() public virtual void ExitAsync()
{ {
//isExiting = true; //isExiting = true;
if (disposed) throw new ObjectDisposedException("GameWindow");
UpdateFrame += CallExitInternal; UpdateFrame += CallExitInternal;
} }
@ -315,7 +317,7 @@ namespace OpenTK
/// </summary> /// </summary>
public bool IsIdle public bool IsIdle
{ {
get { return glWindow.IsIdle; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.IsIdle; }
} }
#endregion #endregion
@ -328,8 +330,8 @@ namespace OpenTK
/// </summary> /// </summary>
public bool Fullscreen public bool Fullscreen
{ {
get { return glWindow.Fullscreen; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.Fullscreen; }
set { glWindow.Fullscreen = value; } set { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Fullscreen = value; }
} }
#endregion #endregion
@ -337,12 +339,15 @@ namespace OpenTK
#region public IGraphicsContext Context #region public IGraphicsContext Context
/// <summary> /// <summary>
/// Returns the opengl IGLontext associated with the current GameWindow. /// Returns the opengl IGraphicsContext associated with the current GameWindow.
/// Forces window creation.
/// </summary> /// </summary>
public IGraphicsContext Context public IGraphicsContext Context
{ {
get { return glContext; } get
{
if (disposed) throw new ObjectDisposedException("GameWindow");
return glContext;
}
} }
#endregion #endregion
@ -367,11 +372,13 @@ namespace OpenTK
public string Title public string Title
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
return glWindow.Title; return glWindow.Title;
} }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
glWindow.Title = value; glWindow.Title = value;
} }
} }
@ -404,7 +411,7 @@ namespace OpenTK
public IWindowInfo WindowInfo public IWindowInfo WindowInfo
{ {
get { return glWindow.WindowInfo; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return glWindow.WindowInfo; }
} }
#endregion #endregion
@ -436,7 +443,8 @@ namespace OpenTK
/// (while the opengl context still exists), to allow resource cleanup. /// (while the opengl context still exists), to allow resource cleanup.
/// </summary> /// </summary>
public void DestroyWindow() public void DestroyWindow()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (Exists) if (Exists)
glWindow.DestroyWindow(); glWindow.DestroyWindow();
else else
@ -452,7 +460,8 @@ namespace OpenTK
/// </summary> /// </summary>
/// <see cref="public virtual void Run(double update_frequency, double render_frequency)"/> /// <see cref="public virtual void Run(double update_frequency, double render_frequency)"/>
public void Run() public void Run()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
Run(0.0, 0.0); Run(0.0, 0.0);
} }
@ -462,7 +471,8 @@ namespace OpenTK
/// </summary> /// </summary>
/// <see cref="public virtual void Run(double updateFrequency, double renderFrequency)"/> /// <see cref="public virtual void Run(double updateFrequency, double renderFrequency)"/>
public void Run(double updateFrequency) public void Run(double updateFrequency)
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
Run(updateFrequency, 0.0); Run(updateFrequency, 0.0);
} }
@ -472,7 +482,8 @@ namespace OpenTK
/// <param name="updates_per_second">The frequency of UpdateFrame events.</param> /// <param name="updates_per_second">The frequency of UpdateFrame events.</param>
/// <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");
try try
{ {
if (updates_per_second < 0.0 || updates_per_second > 200.0) if (updates_per_second < 0.0 || updates_per_second > 200.0)
@ -617,8 +628,9 @@ namespace OpenTK
if (Exists) if (Exists)
{ {
glContext.Dispose(); glContext.Dispose();
glWindow.DestroyWindow(); glContext = null;
glWindow.DestroyWindow();
} }
while (this.Exists) while (this.Exists)
this.ProcessEvents(); this.ProcessEvents();
@ -641,7 +653,8 @@ namespace OpenTK
/// </para> /// </para>
/// </remarks> /// </remarks>
public void ProcessEvents() public void ProcessEvents()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (!isExiting) if (!isExiting)
glWindow.InputDriver.Poll(); glWindow.InputDriver.Poll();
glWindow.ProcessEvents(); glWindow.ProcessEvents();
@ -663,7 +676,7 @@ namespace OpenTK
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
private void OnRenderFrameInternal(RenderFrameEventArgs e) private void OnRenderFrameInternal(RenderFrameEventArgs e)
{ {
if (RenderFrame != null) if (RenderFrame != null)
RenderFrame(this, e); RenderFrame(this, e);
@ -679,7 +692,8 @@ namespace OpenTK
/// The base implementation (base.OnRenderFrame) is empty, there is no need to call it. /// The base implementation (base.OnRenderFrame) is empty, there is no need to call it.
/// </remarks> /// </remarks>
public virtual void OnRenderFrame(RenderFrameEventArgs e) public virtual void OnRenderFrame(RenderFrameEventArgs e)
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
} }
/// <summary> /// <summary>
@ -717,7 +731,8 @@ namespace OpenTK
/// The base implementation (base.OnUpdateFrame) is empty, there is no need to call it. /// The base implementation (base.OnUpdateFrame) is empty, there is no need to call it.
/// </remarks> /// </remarks>
public virtual void OnUpdateFrame(UpdateFrameEventArgs e) public virtual void OnUpdateFrame(UpdateFrameEventArgs e)
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
} }
/// <summary> /// <summary>
@ -767,7 +782,8 @@ namespace OpenTK
/// </summary> /// </summary>
/// <param name="e">Not used.</param> /// <param name="e">Not used.</param>
public virtual void OnLoad(EventArgs e) public virtual void OnLoad(EventArgs e)
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
} }
#endregion #endregion
@ -799,7 +815,8 @@ namespace OpenTK
/// </summary> /// </summary>
/// <param name="e">Not used.</param> /// <param name="e">Not used.</param>
public virtual void OnUnload(EventArgs e) public virtual void OnUnload(EventArgs e)
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
} }
#endregion #endregion
@ -814,7 +831,7 @@ namespace OpenTK
/// </summary> /// </summary>
public bool IsExiting public bool IsExiting
{ {
get { return isExiting; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return isExiting; }
} }
#endregion #endregion
@ -827,7 +844,8 @@ namespace OpenTK
public KeyboardDevice Keyboard public KeyboardDevice Keyboard
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
//if (input_driver.Keyboard.Count > 0) //if (input_driver.Keyboard.Count > 0)
// return input_driver.Keyboard[0]; // return input_driver.Keyboard[0];
//else //else
@ -850,7 +868,8 @@ namespace OpenTK
public MouseDevice Mouse public MouseDevice Mouse
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
//if (input_driver.Mouse.Count > 0) //if (input_driver.Mouse.Count > 0)
// return input_driver.Mouse[0]; // return input_driver.Mouse[0];
//else //else
@ -873,11 +892,13 @@ namespace OpenTK
public VSyncMode VSync public VSyncMode VSync
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
return vsync; return vsync;
} }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (value == VSyncMode.Off) if (value == VSyncMode.Off)
Context.VSync = false; Context.VSync = false;
else else
@ -897,7 +918,8 @@ namespace OpenTK
/// </summary> /// </summary>
/// <remarks>Calling this function is equivalent to calling Context.SwapBuffers()</remarks> /// <remarks>Calling this function is equivalent to calling Context.SwapBuffers()</remarks>
public void SwapBuffers() public void SwapBuffers()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
this.Context.SwapBuffers(); this.Context.SwapBuffers();
} }
@ -930,11 +952,13 @@ namespace OpenTK
public double TargetRenderPeriod public double TargetRenderPeriod
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
return target_render_period; return target_render_period;
} }
set set
{ {
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 = target_render_period_doubled = 0.0;
@ -962,13 +986,15 @@ namespace OpenTK
public double TargetRenderFrequency public double TargetRenderFrequency
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (TargetRenderPeriod == 0.0) if (TargetRenderPeriod == 0.0)
return 0.0; return 0.0;
return 1.0 / TargetRenderPeriod; return 1.0 / TargetRenderPeriod;
} }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (value < 1.0) if (value < 1.0)
{ {
TargetRenderPeriod = 0.0; TargetRenderPeriod = 0.0;
@ -995,11 +1021,13 @@ namespace OpenTK
public double TargetUpdatePeriod public double TargetUpdatePeriod
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
return target_update_period; return target_update_period;
} }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (value <= 0.005) if (value <= 0.005)
{ {
target_update_period = 0.0; target_update_period = 0.0;
@ -1026,13 +1054,15 @@ namespace OpenTK
public double TargetUpdateFrequency public double TargetUpdateFrequency
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (TargetUpdatePeriod == 0.0) if (TargetUpdatePeriod == 0.0)
return 0.0; return 0.0;
return 1.0 / TargetUpdatePeriod; return 1.0 / TargetUpdatePeriod;
} }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (value < 1.0) if (value < 1.0)
{ {
TargetUpdatePeriod = 0.0; TargetUpdatePeriod = 0.0;
@ -1055,7 +1085,8 @@ namespace OpenTK
public double RenderFrequency public double RenderFrequency
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (render_period == 0.0) if (render_period == 0.0)
return 1.0; return 1.0;
return 1.0 / render_period; return 1.0 / render_period;
@ -1072,7 +1103,8 @@ namespace OpenTK
public double RenderPeriod public double RenderPeriod
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
return render_period; return render_period;
} }
} }
@ -1087,7 +1119,8 @@ namespace OpenTK
public double UpdateFrequency public double UpdateFrequency
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (update_period == 0.0) if (update_period == 0.0)
return 1.0; return 1.0;
return 1.0 / update_period; return 1.0 / update_period;
@ -1104,7 +1137,8 @@ namespace OpenTK
public double UpdatePeriod public double UpdatePeriod
{ {
get get
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
return update_period; return update_period;
} }
} }
@ -1118,8 +1152,8 @@ namespace OpenTK
/// </summary> /// </summary>
public double RenderTime public double RenderTime
{ {
get { return render_time; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return render_time; }
protected set { render_time = value; } protected set { if (disposed) throw new ObjectDisposedException("GameWindow"); render_time = value; }
} }
#endregion #endregion
@ -1131,7 +1165,7 @@ namespace OpenTK
/// </summary> /// </summary>
public double UpdateTime public double UpdateTime
{ {
get { return update_time; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return update_time; }
} }
#endregion #endregion
@ -1147,9 +1181,10 @@ namespace OpenTK
/// </summary> /// </summary>
public int Width public int Width
{ {
get { return width; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return width; }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (value == this.Width) if (value == this.Width)
{ {
return; return;
@ -1174,9 +1209,10 @@ namespace OpenTK
/// </summary> /// </summary>
public int Height public int Height
{ {
get { return height; } get { if (disposed) throw new ObjectDisposedException("GameWindow"); return height; }
set set
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
if (value == this.Height) if (value == this.Height)
{ {
return; return;
@ -1205,8 +1241,8 @@ namespace OpenTK
/// </summary> /// </summary>
public event ResizeEvent Resize public event ResizeEvent Resize
{ {
add { glWindow.Resize += value; } add { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Resize += value; }
remove { glWindow.Resize -= value; } remove { if (disposed) throw new ObjectDisposedException("GameWindow"); glWindow.Resize -= value; }
} }
/// <summary> /// <summary>
@ -1231,7 +1267,8 @@ namespace OpenTK
/// </summary> /// </summary>
/// <param name="e">Contains information about the Resize event.</param> /// <param name="e">Contains information about the Resize event.</param>
protected virtual void OnResize(ResizeEventArgs e) protected virtual void OnResize(ResizeEventArgs e)
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
} }
#endregion #endregion
@ -1303,21 +1340,14 @@ namespace OpenTK
#endif #endif
#region --- IDisposable Members --- #region --- IDisposable Members ---
/// <summary>
/// Not used yet.
/// </summary>
private void DisposeInternal()
{
Dispose(); // User overridable Dispose method.
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary> /// <summary>
/// Disposes of the GameWindow, releasing all resources consumed by it. /// Disposes of the GameWindow, releasing all resources consumed by it.
/// </summary> /// </summary>
public virtual void Dispose() public virtual void Dispose()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow");
Dispose(true);
GC.SuppressFinalize(this);
} }
private void Dispose(bool manual) private void Dispose(bool manual)
@ -1326,8 +1356,11 @@ namespace OpenTK
{ {
if (manual) if (manual)
{ {
if (glContext != null) if (glContext != null)
glContext.Dispose(); {
glContext.Dispose();
glContext = null;
}
if (glWindow != null) if (glWindow != null)
{ {
@ -1340,10 +1373,10 @@ namespace OpenTK
} }
/// <summary>Finalizes unmanaged resources consumed by the GameWindow.</summary> /// <summary>Finalizes unmanaged resources consumed by the GameWindow.</summary>
~GameWindow() //~GameWindow()
{ //{
Dispose(false); // Dispose(false);
} //}
#endregion #endregion
} }

View file

@ -83,8 +83,11 @@ namespace OpenTK.Graphics
implementation = new OpenTK.Platform.X11.X11GLContext(mode, window, shareContext, DirectRendering); implementation = new OpenTK.Platform.X11.X11GLContext(mode, window, shareContext, DirectRendering);
else else
throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); 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(); //(implementation as IGraphicsContextInternal).LoadAll();
} }
@ -118,14 +121,17 @@ namespace OpenTK.Graphics
public static GraphicsContext CurrentContext public static GraphicsContext CurrentContext
{ {
get get
{ {
if (available_contexts.Count > 0) lock (context_lock)
{ {
ContextHandle handle = GetCurrentContext(); if (available_contexts.Count > 0)
if (handle.Handle != IntPtr.Zero) {
return (GraphicsContext)available_contexts[handle].Target; ContextHandle handle = GetCurrentContext();
if (handle.Handle != IntPtr.Zero)
return (GraphicsContext)available_contexts[handle].Target;
}
return null;
} }
return null;
} }
//set //set
//{ //{
@ -199,8 +205,11 @@ namespace OpenTK.Graphics
void CreateContext(bool direct, IGraphicsContext source) void CreateContext(bool direct, IGraphicsContext source)
{ {
this.Destroy += ContextDestroyed; 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); //OpenTK.Graphics.OpenGL.GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit);
//if (StaticGetCurrentContext == null) //if (StaticGetCurrentContext == null)
@ -363,13 +372,15 @@ namespace OpenTK.Graphics
void Dispose(bool manual) void Dispose(bool manual)
{ {
if (!disposed) if (!disposed)
{ {
Debug.WriteLine("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString());
lock (context_lock)
{
available_contexts.Remove((this as IGraphicsContextInternal).Context);
}
if (manual) if (manual)
{ {
Debug.WriteLine("Disposing context.");
available_contexts.Remove((this as IGraphicsContextInternal).Context);
// TODO: Check if this is safe
if (implementation != null) if (implementation != null)
implementation.Dispose(); implementation.Dispose();
} }
@ -377,10 +388,10 @@ namespace OpenTK.Graphics
} }
} }
~GraphicsContext() //~GraphicsContext()
{ //{
this.Dispose(false); // this.Dispose(false);
} //}
#endregion #endregion
} }
@ -398,4 +409,4 @@ namespace OpenTK.Graphics
} }
#endregion #endregion
} }

View file

@ -66,7 +66,9 @@ namespace OpenTK.Platform.X11
#endregion #endregion
static API() static API()
{ {
Debug.Print("Initializing threaded X11: {0}.", Functions.XInitThreads().ToString());
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
// Bad idea - Windows.Forms will steal our events! // Bad idea - Windows.Forms will steal our events!

View file

@ -40,6 +40,35 @@ namespace OpenTK.Platform.X11
using Status = System.Int32; using Status = System.Int32;
using SizeID = System.UInt16; 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 #endregion
internal static partial class Functions internal static partial class Functions
@ -382,7 +411,12 @@ namespace OpenTK.Platform.X11
} }
[DllImport("libX11")] [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);
} }
} }

View file

@ -63,13 +63,18 @@ namespace OpenTK.Platform.X11
XVisualInfo info = new XVisualInfo(); XVisualInfo info = new XVisualInfo();
info.visualid = (IntPtr)mode.Index; info.visualid = (IntPtr)mode.Index;
info.screen = currentWindow.Screen; info.screen = currentWindow.Screen;
int items; int items;
IntPtr vs = Functions.XGetVisualInfo(currentWindow.Display, XVisualInfoMask.ID | XVisualInfoMask.Screen, ref info, out items);
if (items == 0) lock (API.Lock)
throw new GraphicsModeException(String.Format("Invalid GraphicsMode specified ({0}).", mode)); {
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; return info;
} }
@ -88,26 +93,29 @@ namespace OpenTK.Platform.X11
Debug.Write(direct ? "direct, " : "indirect, "); Debug.Write(direct ? "direct, " : "indirect, ");
Debug.Write(shareHandle.Handle == IntPtr.Zero ? "not shared... " : Debug.Write(shareHandle.Handle == IntPtr.Zero ? "not shared... " :
String.Format("shared with ({0})... ", shareHandle)); 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 creation succeeded, return.
context = Glx.CreateContext(window.Display, ref info, shareHandle.Handle, direct); if (context != IntPtr.Zero)
{
Debug.Print("done! (id: {0})", context);
return;
}
// Context creation succeeded, return. // Context creation failed. Retry with a non-shared context with the direct/indirect bit flipped.
if (context != IntPtr.Zero) Debug.Print("failed.");
{ Debug.Write(String.Format("Creating OpenGL context: {0}, not shared... ", !direct ? "direct" : "indirect"));
Debug.Print("done! (id: {0})", context); context = Glx.CreateContext(window.Display, ref info, IntPtr.Zero, !direct);
return; if (context != IntPtr.Zero)
} {
Debug.Print("done! (id: {0})", context);
// Context creation failed. Retry with a non-shared context with the direct/indirect bit flipped. return;
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."); Debug.Print("failed.");
throw new GraphicsModeException("Failed to create OpenGL context. Glx.CreateContext call returned 0."); throw new GraphicsModeException("Failed to create OpenGL context. Glx.CreateContext call returned 0.");
@ -194,10 +202,10 @@ namespace OpenTK.Platform.X11
set set
{ {
if (vsync_supported) if (vsync_supported)
{ {
int error_code = Glx.Sgi.SwapInterval(value ? 1 : 0); int error_code = Glx.Sgi.SwapInterval(value ? 1 : 0);
if (error_code != 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; vsync_interval = value ? 1 : 0;
} }
} }
@ -286,7 +294,7 @@ namespace OpenTK.Platform.X11
#region static ContextHandle GetCurrentContext() #region static ContextHandle GetCurrentContext()
static ContextHandle GetCurrentContext() static ContextHandle GetCurrentContext()
{ {
return (ContextHandle)Glx.GetCurrentContext(); return (ContextHandle)Glx.GetCurrentContext();
} }
@ -305,16 +313,22 @@ namespace OpenTK.Platform.X11
private void Dispose(bool manuallyCalled) private void Dispose(bool manuallyCalled)
{ {
if (!disposed) if (!disposed)
{ {
// Clean unmanaged resources: // Clean unmanaged resources:
try
Glx.MakeCurrent(currentWindow.Display, IntPtr.Zero, IntPtr.Zero); {
Glx.DestroyContext(currentWindow.Display, context); Functions.XLockDisplay(currentWindow.Display);
//API.Free(visual); Glx.MakeCurrent(currentWindow.Display, IntPtr.Zero, IntPtr.Zero);
Glx.DestroyContext(currentWindow.Display, context);
//Functions.XFree(visual);
}
finally
{
Functions.XUnlockDisplay(currentWindow.Display);
}
if (manuallyCalled) if (manuallyCalled)
{ {
// Safe to clean managed resources, too
} }
} }
disposed = true; disposed = true;

View file

@ -94,12 +94,22 @@ namespace OpenTK.Platform.X11
//window.Screen = (int)xplatui.GetField("ScreenNo", //window.Screen = (int)xplatui.GetField("ScreenNo",
// System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // 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. // 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 window.Display = API.DefaultDisplay;//Functions.XOpenDisplay(IntPtr.Zero); // IntPtr.Zero == default display
if (window.Display == IntPtr.Zero) if (window.Display == IntPtr.Zero)
throw new Exception("Could not open connection to X"); 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); Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen, window.RootWindow);
RegisterAtoms(window); RegisterAtoms(window);
@ -144,57 +154,61 @@ namespace OpenTK.Platform.X11
if (width <= 0) throw new ArgumentOutOfRangeException("width", "Must be higher than zero."); 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 (height <= 0) throw new ArgumentOutOfRangeException("height", "Must be higher than zero.");
if (exists) throw new InvalidOperationException("A render window already exists."); 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(); // Create a window on this display using the visual above
info.visualid = mode.Index; Debug.Write("Opening render window... ");
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 XSetWindowAttributes attributes = new XSetWindowAttributes();
Debug.Write("Opening render window... "); 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(); uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask |
attributes.background_pixel = IntPtr.Zero; (uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel;
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 | window.WindowHandle = Functions.XCreateWindow(window.Display, window.RootWindow,
(uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel; 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, if (window.WindowHandle == IntPtr.Zero)
0, 0, width, height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/, throw new ApplicationException("XCreateWindow call failed (returned 0).");
(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);
//XVisualInfo vis = window.VisualInfo;
//Glx.CreateContext(window.Display, ref vis, IntPtr.Zero, true);
}
context = new GraphicsContext(mode, window); context = new GraphicsContext(mode, window);
// Set the window hints // Set the window hints
XSizeHints hints = new XSizeHints(); XSizeHints hints = new XSizeHints();
hints.x = 0; hints.x = 0;
hints.y = 0; hints.y = 0;
hints.width = width; hints.width = width;
hints.height = height; hints.height = height;
hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition); hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition);
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints); lock (API.Lock)
{
// Register for window destroy notification Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
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);
// 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; Top = Left = 0;
Right = Width; Right = Width;
Bottom = Height; Bottom = Height;
@ -206,10 +220,11 @@ namespace OpenTK.Platform.X11
//Functions.XSetWMProperties(display, window, name, name, 0, /*None*/ null, 0, hints); //Functions.XSetWMProperties(display, window, name, name, 0, /*None*/ null, 0, hints);
Debug.Print("done! (id: {0})", window.WindowHandle); Debug.Print("done! (id: {0})", window.WindowHandle);
//(glContext as IGLContextCreationHack).SetWindowHandle(window.Handle); lock (API.Lock)
{
API.MapRaised(window.Display, window.WindowHandle); API.MapRaised(window.Display, window.WindowHandle);
}
mapped = true; mapped = true;
//context.CreateContext(true, null); //context.CreateContext(true, null);
@ -663,18 +678,24 @@ namespace OpenTK.Platform.X11
private void Dispose(bool manuallyCalled) private void Dispose(bool manuallyCalled)
{ {
if (!disposed) if (!disposed)
{ {
if (window != null) if (window != null && window.WindowHandle != IntPtr.Zero)
{ {
if (window.WindowHandle != IntPtr.Zero) try
Functions.XDestroyWindow(window.Display, window.WindowHandle); {
//if (window.Display != IntPtr.Zero) Functions.XLockDisplay(window.Display);
// Functions.XCloseDisplay(window.Display); Functions.XDestroyWindow(window.Display, window.WindowHandle);
}
finally
{
Functions.XUnlockDisplay(window.Display);
}
window = null; window = null;
} }
if (manuallyCalled) if (manuallyCalled)
{ {
} }
disposed = true; disposed = true;
} }

View file

@ -80,9 +80,12 @@ namespace OpenTK.Platform.X11
visualAttributes.Add((int)0); visualAttributes.Add((int)0);
// Select a visual that matches the parameters set by the user. // 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); int screen = Functions.XDefaultScreen(display);
IntPtr root = Functions.XRootWindow(display, screen); IntPtr root = Functions.XRootWindow(display, screen);
Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root); 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. ++buffers; // the above lines returns 0 - false and 1 - true.
int st; int st;
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out 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, gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples,
new ColorFormat(ar, ag, ab, aa), buffers, stereo); new ColorFormat(ar, ag, ab, aa), buffers, stereo);
}
//Functions.XCloseDisplay(display); finally
{
Functions.XUnlockDisplay(display);
} }
// Prepare Windows.Forms for creating OpenGL drawables. // Prepare Windows.Forms for creating OpenGL drawables.
lock (API.Lock) //lock (API.Lock)
{ //{
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); // Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", // IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
IntPtr root = (IntPtr)xplatui.GetField("RootWindow", // IntPtr root = (IntPtr)xplatui.GetField("RootWindow",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
int screen = (int)xplatui.GetField("ScreenNo", // int screen = (int)xplatui.GetField("ScreenNo",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
//xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) //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) //xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
// .SetValue(null, Functions.XCreateColormap(display, root, visual, 0)); // .SetValue(null, Functions.XCreateColormap(display, root, visual, 0));
} //}
Functions.XFree(visual); try
{
Functions.XLockDisplay(display);
Functions.XFree(visual);
}
finally
{
Functions.XUnlockDisplay(display);
}
return gfx; return gfx;
} }