Hooks for garbage-collectable OpenGL resources.

the [...]GLNative classes now use GLContext instead of the platform-specific [...]GLContext implementations.
Updated the IGLContext interface with functions to query the current context.
This commit is contained in:
the_fiddler 2007-12-09 18:15:51 +00:00
parent 84c64fbfce
commit 107951c4d1
12 changed files with 313 additions and 175 deletions

View file

@ -12,7 +12,7 @@ using OpenTK.Math;
namespace Examples.Tests namespace Examples.Tests
{ {
[Example("Math speed test", ExampleCategory.Test, 2, false)] [Example("Math speed test", ExampleCategory.Test, 2/*, false*/)]
public class MathSpeed public class MathSpeed
{ {
public static void Main() public static void Main()
@ -31,7 +31,7 @@ namespace Examples.Tests
Vector3.Add(ref a, ref b, out res); Vector3.Add(ref a, ref b, out res);
res = a + b; res = a + b;
res = Vector3.Zero; res = Vector3.Zero;
/*
watch.Reset(); watch.Reset();
watch.Start(); watch.Start();
for (int i = 100000000; --i != 0; ) for (int i = 100000000; --i != 0; )
@ -63,6 +63,29 @@ namespace Examples.Tests
watch.Stop(); watch.Stop();
res += res; // To make sure the whole for-loop isn't optimized-out res += res; // To make sure the whole for-loop isn't optimized-out
Trace.WriteLine(String.Format("Vector3.Add(ref a, ref b, out res)\t{0}ns", (watch.Elapsed.TotalSeconds / 10.0).ToString())); Trace.WriteLine(String.Format("Vector3.Add(ref a, ref b, out res)\t{0}ns", (watch.Elapsed.TotalSeconds / 10.0).ToString()));
*/
a = Vector3.UnitX;
b = Vector3.UnitY;
res = Vector3.Add(ref a, ref b);
Trace.WriteLine(res.ToString());
a = Vector3.UnitX;
b = Vector3.UnitY;
Vector3.Add(a, b, out res);
Trace.WriteLine(res.ToString());
Vector2Im q = new Vector2(0.0f, 1.0f);
Vector2Im p = new Vector2(2.0f, 3.0f);
Vector2Im s = Vector2.Add(p, q);
p = s + q;
}
static Vector3 pos = new Vector3();
static Vector3 Pos
{
get { return pos; }
set { pos = value; }
} }
} }
} }

View file

@ -120,6 +120,9 @@ namespace Examples.Tutorial
else if (scroll_speed < 0.0f && current_position < warparound_position) else if (scroll_speed < 0.0f && current_position < warparound_position)
current_position = initial_position; current_position = initial_position;
TextHandle t = null;
text.Prepare((1.0 / e.Time).ToString(), serif, out t);
// TextPrinter.Begin() sets up a 2d orthographic projection, with the x axis // TextPrinter.Begin() sets up a 2d orthographic projection, with the x axis
// moving from 0 to viewport.Width (left to right) and the y axis from // moving from 0 to viewport.Width (left to right) and the y axis from
// 0 to viewport.Height (top to bottom). This is the typical coordinate system // 0 to viewport.Height (top to bottom). This is the typical coordinate system
@ -127,6 +130,13 @@ namespace Examples.Tutorial
// TextPrinter.End() restores your previous projection/modelview matrices. // TextPrinter.End() restores your previous projection/modelview matrices.
text.Begin(); text.Begin();
using (t)
{
//text.Begin();
text.Draw(t);
//text.End();
}
GL.Translate(0.0f, current_position, 0.0f); GL.Translate(0.0f, current_position, 0.0f);
text.Draw(poem_handle); text.Draw(poem_handle);

View file

@ -17,10 +17,16 @@ namespace OpenTK
/// </summary> /// </summary>
public class GLContext : IGLContext public class GLContext : IGLContext
{ {
/// <summary> IGLContext implementation; // The actual render context implementation for the underlying platform.
/// The actual render context implementation for the underlying platform. List<IDisposable> dispose_queue = new List<IDisposable>();
/// </summary>
private IGLContext implementation; static SortedList<long, WeakReference> available_contexts =
new SortedList<long, WeakReference>(); // Contains all available OpenGL contexts.
delegate IntPtr GetCurrentContextDelegate();
static GetCurrentContextDelegate StaticGetCurrentContext;
#region public GLContext(DisplayMode mode, IWindowInfo window)
/// <summary> /// <summary>
/// Constructs a new GLContext with the specified DisplayMode, and bound to the specified IWindowInfo. /// Constructs a new GLContext with the specified DisplayMode, and bound to the specified IWindowInfo.
@ -29,6 +35,9 @@ namespace OpenTK
/// <param name="window"></param> /// <param name="window"></param>
public GLContext(DisplayMode mode, IWindowInfo window) public GLContext(DisplayMode mode, IWindowInfo window)
{ {
if (available_contexts.Count == 0)
available_contexts.Add(0, new WeakReference(null));
switch (Environment.OSVersion.Platform) switch (Environment.OSVersion.Platform)
{ {
case PlatformID.Unix: case PlatformID.Unix:
@ -48,6 +57,17 @@ namespace OpenTK
} }
} }
#endregion
#region public static IGLContext CurrentContext
public static GLContext CurrentContext
{
get { return (GLContext)available_contexts[StaticGetCurrentContext().ToInt64()].Target; }
}
#endregion
#region --- IGLContext Members --- #region --- IGLContext Members ---
/// <summary> /// <summary>
@ -79,7 +99,7 @@ namespace OpenTK
/// </summary> /// </summary>
public void CreateContext() public void CreateContext()
{ {
implementation.CreateContext(); CreateContext(true, null);
} }
/// <summary> /// <summary>
@ -99,7 +119,7 @@ namespace OpenTK
/// </remarks> /// </remarks>
public void CreateContext(bool direct) public void CreateContext(bool direct)
{ {
implementation.CreateContext(direct); CreateContext(direct, null);
} }
/// <summary> /// <summary>
@ -112,6 +132,10 @@ namespace OpenTK
public void CreateContext(bool direct, IGLContext source) public void CreateContext(bool direct, IGLContext source)
{ {
implementation.CreateContext(direct, source); implementation.CreateContext(direct, source);
available_contexts.Add(Context.ToInt64(), new WeakReference(this));
if (StaticGetCurrentContext == null)
StaticGetCurrentContext = implementation.GetCurrentContext;
} }
/// <summary> /// <summary>
@ -130,6 +154,33 @@ namespace OpenTK
implementation.MakeCurrent(); implementation.MakeCurrent();
} }
/// <summary>
/// Gets a System.Boolean indicating whether this Context is current in the calling thread.
/// </summary>
public bool IsCurrent
{
get { return implementation.IsCurrent; }
}
/// <summary>
/// Gets a System.IntPtr containing the handle to the OpenGL context which is current in the
/// calling thread, or IntPtr.Zero if no OpenGL context is current.
/// </summary>
/// <returns>A System.IntPtr that holds the handle to the current OpenGL context.</returns>
public IntPtr GetCurrentContext()
{
return implementation.GetCurrentContext();
}
/// <summary>
/// Raised when a Context is destroyed.
/// </summary>
public event DestroyEvent<IGLContext> Destroy
{
add { implementation.Destroy += value; }
remove { implementation.Destroy -= value; }
}
/// <summary> /// <summary>
/// Gets the address of an OpenGL extension function. /// Gets the address of an OpenGL extension function.
/// </summary> /// </summary>
@ -162,6 +213,28 @@ namespace OpenTK
set { implementation.VSync = value; } set { implementation.VSync = value; }
} }
/// <summary>
/// Registers an OpenGL resource for disposal.
/// </summary>
/// <param name="resource">The OpenGL resource to dispose.</param>
public void RegisterForDisposal(IDisposable resource)
{
GC.KeepAlive(resource);
dispose_queue.Add(resource);
}
/// <summary>
/// Disposes all registered OpenGL resources.
/// </summary>
public void DisposeResources()
{
foreach (IDisposable resource in dispose_queue)
{
resource.Dispose();
}
dispose_queue.Clear();
}
#endregion #endregion
#region IDisposable Members #region IDisposable Members
@ -171,6 +244,7 @@ namespace OpenTK
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
available_contexts.Remove(Context.ToInt64());
implementation.Dispose(); implementation.Dispose();
} }

View file

@ -200,7 +200,7 @@ namespace OpenTK
// specific depth for the DisplayMode - we let the driver select one instead. // specific depth for the DisplayMode - we let the driver select one instead.
display_mode.Color = new ColorMode(0); display_mode.Color = new ColorMode(0);
context = new GLContext(display_mode, info); context = new GLContext(display_mode, info);
context.CreateContext(); context.CreateContext(true, null);
idle = new PlatformIdle(info); idle = new PlatformIdle(info);
} }
else else

View file

@ -71,6 +71,8 @@ namespace OpenTK
//InputDriver input_driver; //InputDriver input_driver;
GLContext glContext;
#endregion #endregion
#region --- Internal Properties --- #region --- Internal Properties ---
@ -126,6 +128,9 @@ namespace OpenTK
glWindow.Destroy += new DestroyEvent(glWindow_Destroy); glWindow.Destroy += new DestroyEvent(glWindow_Destroy);
CreateWindow(mode, title); CreateWindow(mode, title);
glContext = new GLContext(mode, glWindow.WindowInfo);
glContext.CreateContext();
//this.vsync = VSyncMode.Adaptive; //this.vsync = VSyncMode.Adaptive;
this.VSync = VSyncMode.On; this.VSync = VSyncMode.On;
} }
@ -199,7 +204,8 @@ namespace OpenTK
mode = new DisplayMode(640, 480); mode = new DisplayMode(640, 480);
this.CreateWindow(mode); this.CreateWindow(mode);
} }
return glWindow.Context; //return glWindow.Context;
return glContext;
} }
} }
@ -355,22 +361,11 @@ namespace OpenTK
{ {
if (!Exists) if (!Exists)
{ {
try glWindow.CreateWindow(mode);
{ this.Title = title;
glWindow.CreateWindow(mode);
this.Title = title;
//input_driver = new InputDriver(this);
}
catch (ApplicationException expt)
{
Debug.Print(expt.ToString());
throw;
}
} }
else else
{
throw new InvalidOperationException("A render window already exists for this GameWindow."); throw new InvalidOperationException("A render window already exists for this GameWindow.");
}
} }
#endregion #endregion

View file

@ -12,6 +12,7 @@ namespace OpenTK.Platform
{ {
/// <summary> /// <summary>
/// An empty IGLContext implementation to be used inside the Visual Studio designer. /// An empty IGLContext implementation to be used inside the Visual Studio designer.
/// This class supports OpenTK, and is not intended for use by OpenTK programs.
/// </summary> /// </summary>
internal sealed class DummyGLContext : IGLContext internal sealed class DummyGLContext : IGLContext
{ {
@ -37,6 +38,20 @@ namespace OpenTK.Platform
public void SwapBuffers() { } public void SwapBuffers() { }
public void MakeCurrent() { } public void MakeCurrent() { }
public bool IsCurrent { get { return true; } }
public IntPtr GetCurrentContext() { return IntPtr.Zero; }
public event DestroyEvent<IGLContext> Destroy;
public void RegisterForDisposal(IDisposable resource)
{
throw new NotImplementedException("Use the general GLContext class instead.");
}
public void DisposeResources()
{
throw new NotImplementedException("Use the general GLContext class instead.");
}
public IntPtr GetAddress(string function) { return IntPtr.Zero; } public IntPtr GetAddress(string function) { return IntPtr.Zero; }
public IEnumerable<DisplayMode> GetDisplayModes() { return null; } public IEnumerable<DisplayMode> GetDisplayModes() { return null; }

View file

@ -30,28 +30,6 @@ namespace OpenTK.Platform
/// </summary> /// </summary>
DisplayMode Mode { get; } DisplayMode Mode { get; }
/// <summary>
/// Creates an OpenGL context.
/// </summary>
void CreateContext();
/// <summary>
/// Creates an OpenGL context with a direct or indirect rendering mode. This parameter is ignored
/// on Windows platforms (direct mode only).
/// </summary>
/// <param name="direct">Set to true for direct rendering or false otherwise.</param>
/// <remarks>
/// <para>
/// Direct rendering is the default rendering mode for OpenTK, since it can provide higher performance
/// in some circumastances.
/// </para>
/// <para>
/// The 'direct' parameter is a hint, and will ignored if the specified mode is not supported (e.g. setting
/// indirect rendering on Windows platforms).
/// </para>
/// </remarks>
void CreateContext(bool direct);
/// <summary> /// <summary>
/// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the /// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the
/// specified IGLContext. /// specified IGLContext.
@ -71,6 +49,23 @@ namespace OpenTK.Platform
/// </summary> /// </summary>
void MakeCurrent(); void MakeCurrent();
/// <summary>
/// Gets a System.Boolean indicating whether this Context is current in the calling thread.
/// </summary>
bool IsCurrent { get; }
/// <summary>
/// Gets a System.IntPtr containing the handle to the OpenGL context which is current in the
/// calling thread, or IntPtr.Zero if no OpenGL context is current.
/// </summary>
/// <returns>A System.IntPtr that holds the handle to the current OpenGL context.</returns>
IntPtr GetCurrentContext();
/// <summary>
/// Raised when a Context is destroyed.
/// </summary>
event DestroyEvent<IGLContext> Destroy;
/// <summary> /// <summary>
/// Gets the address of an OpenGL extension function. /// Gets the address of an OpenGL extension function.
/// </summary> /// </summary>
@ -92,5 +87,24 @@ namespace OpenTK.Platform
/// Gets or sets a value indicating whether VSyncing is enabled. /// Gets or sets a value indicating whether VSyncing is enabled.
/// </summary> /// </summary>
bool VSync { get; set; } bool VSync { get; set; }
/// <summary>
/// Registers an OpenGL resource for disposal.
/// </summary>
/// <param name="resource">The OpenGL resource to dispose.</param>
/// <remarks>
/// You may not destroy OpenGL resources in finalizers, since they run in
/// a different thread. To avoid this problem, use this method to register
/// a resource for disposal during the finalizer call, and call DisposeResources()
/// from the main thread to dispose it.
/// </remarks>
void RegisterForDisposal(IDisposable resource);
/// <summary>
/// Disposes all registered OpenGL resources.
/// </summary>
void DisposeResources();
} }
public delegate void DestroyEvent<T>(T sender, EventArgs e);
} }

View file

@ -27,7 +27,7 @@ namespace OpenTK.Platform
string Title { get; set; } string Title { get; set; }
bool Visible { get; set; } bool Visible { get; set; }
bool IsIdle { get; } bool IsIdle { get; }
IGLContext Context { get; } //IGLContext Context { get; }
IInputDriver InputDriver { get; } IInputDriver InputDriver { get; }
event CreateEvent Create; event CreateEvent Create;

View file

@ -23,7 +23,7 @@ namespace OpenTK.Platform.Windows
/// Provides methods to create and control an opengl context on the Windows platform. /// Provides methods to create and control an opengl context on the Windows platform.
/// This class supports OpenTK, and is not intended for use by OpenTK programs. /// This class supports OpenTK, and is not intended for use by OpenTK programs.
/// </summary> /// </summary>
internal sealed class WinGLContext : OpenTK.Platform.IGLContext, IDisposable internal sealed class WinGLContext : IGLContext
{ {
private IntPtr deviceContext; private IntPtr deviceContext;
private IntPtr renderContext; private IntPtr renderContext;
@ -212,14 +212,11 @@ namespace OpenTK.Platform.Windows
// Do not rely on OpenTK.Platform.Windows.Wgl - the context is not ready yet, // Do not rely on OpenTK.Platform.Windows.Wgl - the context is not ready yet,
// and Wgl extensions will fail to load. // and Wgl extensions will fail to load.
renderContext = Wgl.Imports.CreateContext(deviceContext); renderContext = Wgl.Imports.CreateContext(deviceContext);
if (renderContext != IntPtr.Zero) if (renderContext == IntPtr.Zero)
{
Debug.WriteLine(String.Format("done! (id: {0})", renderContext));
}
else
{
throw new ApplicationException("Could not create OpenGL render context (Wgl.CreateContext() return 0)."); throw new ApplicationException("Could not create OpenGL render context (Wgl.CreateContext() return 0).");
}
Debug.WriteLine(String.Format("done! (id: {0})", renderContext));
Wgl.Imports.MakeCurrent(deviceContext, renderContext); Wgl.Imports.MakeCurrent(deviceContext, renderContext);
Wgl.LoadAll(); Wgl.LoadAll();
GL.LoadAll(); GL.LoadAll();
@ -267,6 +264,36 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region public bool IsCurrent
public bool IsCurrent
{
get { return Wgl.GetCurrentContext() == this.renderContext; }
}
#endregion
#region public IntPtr GetCurrentContext()
public IntPtr GetCurrentContext()
{
return Wgl.GetCurrentContext();
}
#endregion
public event DestroyEvent<IGLContext> Destroy;
public void RegisterForDisposal(IDisposable resource)
{
throw new NotImplementedException("Use the general GLContext class instead.");
}
public void DisposeResources()
{
throw new NotImplementedException("Use the general GLContext class instead.");
}
#region public DisplayMode[] GetDisplayModes() #region public DisplayMode[] GetDisplayModes()
public IEnumerable<DisplayMode> GetDisplayModes() public IEnumerable<DisplayMode> GetDisplayModes()
@ -337,7 +364,6 @@ namespace OpenTK.Platform.Windows
public void Dispose() public void Dispose()
{ {
//Debug.Print("Manually disposing WinGLContext {0}.", this.renderContext);
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
@ -346,9 +372,7 @@ namespace OpenTK.Platform.Windows
{ {
if (!disposed) if (!disposed)
{ {
// Clean unmanaged resources here DestroyContext();
// The following call uses the Debug and Wgl classes, making it unsafe?
ReleaseResources();
if (calledManually) if (calledManually)
{ {
@ -363,10 +387,13 @@ namespace OpenTK.Platform.Windows
Dispose(false); Dispose(false);
} }
#region private void ReleaseResources() #region private void DestroyContext()
private void ReleaseResources() private void DestroyContext()
{ {
if (Destroy != null)
Destroy(this, EventArgs.Empty);
if (renderContext != IntPtr.Zero) if (renderContext != IntPtr.Zero)
{ {
Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero); Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
@ -387,6 +414,7 @@ namespace OpenTK.Platform.Windows
} }
} }
/*
if (opengl32Handle != IntPtr.Zero) if (opengl32Handle != IntPtr.Zero)
{ {
if (!Functions.FreeLibrary(opengl32Handle)) if (!Functions.FreeLibrary(opengl32Handle))
@ -396,6 +424,7 @@ namespace OpenTK.Platform.Windows
} }
opengl32Handle = IntPtr.Zero; opengl32Handle = IntPtr.Zero;
} }
*/
} }
#endregion #endregion

View file

@ -27,7 +27,6 @@ namespace OpenTK.Platform.Windows
{ {
#region --- Fields --- #region --- Fields ---
private WinGLContext glContext;
private DisplayMode mode = new DisplayMode(); private DisplayMode mode = new DisplayMode();
private WinRawInput driver; private WinRawInput driver;
@ -190,15 +189,6 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region public IGLContext Context
public IGLContext Context
{
get { return glContext; }
}
#endregion
#region public bool Fullscreen #region public bool Fullscreen
public bool Fullscreen public bool Fullscreen
@ -286,7 +276,7 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region private void CreateWindow(DisplayMode mode) #region public void CreateWindow(DisplayMode mode)
public void CreateWindow(DisplayMode windowMode) public void CreateWindow(DisplayMode windowMode)
{ {
@ -331,17 +321,14 @@ namespace OpenTK.Platform.Windows
// which is raised CreateHandle() // which is raised CreateHandle()
CreateHandle(cp); CreateHandle(cp);
if (this.Handle != IntPtr.Zero && glContext != null) if (this.Handle != IntPtr.Zero)
{ {
Debug.WriteLine("Window creation was succesful."); Debug.WriteLine("Window creation was succesful.");
exists = true; exists = true;
} }
else else throw new ApplicationException(String.Format(
{ "Could not create native window and/or context. Handle: {0}",
throw new ApplicationException(String.Format( this.Handle));
"Could not create native window and/or context. Handle: {0}, Context {1}",
this.Handle, this.Context.ToString()));
}
Debug.Unindent(); Debug.Unindent();
} }
@ -359,17 +346,6 @@ namespace OpenTK.Platform.Windows
Debug.Print("Window created: {0}", window); Debug.Print("Window created: {0}", window);
try
{
glContext = new WinGLContext(this.mode, this.WindowInfo);
glContext.CreateContext();
}
catch (ApplicationException expt)
{
Debug.Print("Could not create opengl context, error: {0}", expt.ToString());
throw;
}
if (this.Create != null) if (this.Create != null)
this.Create(this, e); this.Create(this, e);
} }
@ -510,7 +486,6 @@ namespace OpenTK.Platform.Windows
if (calledManually) if (calledManually)
{ {
// Safe to clean managed resources // Safe to clean managed resources
glContext.Dispose();
//base.DestroyHandle(); //base.DestroyHandle();
} }
disposed = true; disposed = true;

View file

@ -18,7 +18,7 @@ namespace OpenTK.Platform.X11
/// Provides methods to create and control an opengl context on the X11 platform. /// Provides methods to create and control an opengl context on the X11 platform.
/// This class supports OpenTK, and is not intended for use by OpenTK programs. /// This class supports OpenTK, and is not intended for use by OpenTK programs.
/// </summary> /// </summary>
internal sealed class X11GLContext : OpenTK.Platform.IGLContext internal sealed class X11GLContext : IGLContext
{ {
private IntPtr context; private IntPtr context;
private DisplayMode mode; private DisplayMode mode;
@ -235,11 +235,20 @@ namespace OpenTK.Platform.X11
#endregion #endregion
public bool IsCurrent() public bool IsCurrent
{ {
//return GetCurrentContext() == context;
get { throw new NotImplementedException(); }
}
public IntPtr GetCurrentContext()
{
//return Glx.GetCurrentContext();
throw new NotImplementedException(); throw new NotImplementedException();
} }
public event DestroyEvent<IGLContext> Destroy;
#region public IntPtr GetAddress(string function) #region public IntPtr GetAddress(string function)
public IntPtr GetAddress(string function) public IntPtr GetAddress(string function)
@ -249,6 +258,16 @@ namespace OpenTK.Platform.X11
#endregion #endregion
public void RegisterForDisposal(IDisposable resource)
{
throw new NotImplementedException("Use the general GLContext class instead.");
}
public void DisposeResources()
{
throw new NotImplementedException("Use the general GLContext class instead.");
}
public IEnumerable<DisplayMode> GetDisplayModes() public IEnumerable<DisplayMode> GetDisplayModes()
{ {
throw new Exception("The method or operation is not implemented."); throw new Exception("The method or operation is not implemented.");

View file

@ -25,7 +25,6 @@ namespace OpenTK.Platform.X11
{ {
#region --- Fields --- #region --- Fields ---
private X11GLContext glContext;
private WindowInfo window = new WindowInfo(); private WindowInfo window = new WindowInfo();
private DisplayMode mode = new DisplayMode(); private DisplayMode mode = new DisplayMode();
private X11Input driver; private X11Input driver;
@ -66,9 +65,8 @@ namespace OpenTK.Platform.X11
// Open the display to the X server, and obtain the screen and root window. // Open the display to the X server, and obtain the screen and root window.
window.Display = API.OpenDisplay(null); // null == default display window.Display = API.OpenDisplay(null); // null == 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 = API.DefaultScreen(window.Display); window.Screen = API.DefaultScreen(window.Display);
window.RootWindow = API.RootWindow(window.Display, window.Screen); window.RootWindow = API.RootWindow(window.Display, window.Screen);
@ -240,15 +238,6 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region public IGLContext Context
public OpenTK.Platform.IGLContext Context
{
get { return glContext; }
}
#endregion
#region public IntPtr Handle #region public IntPtr Handle
/// <summary> /// <summary>
@ -361,88 +350,83 @@ namespace OpenTK.Platform.X11
public void CreateWindow(DisplayMode mode) public void CreateWindow(DisplayMode mode)
{ {
if (exists) if (exists)
{
throw new ApplicationException("Render window already exists!"); throw new ApplicationException("Render window already exists!");
}
else
{
Debug.Print("Creating GameWindow with mode: {0}", mode.ToString());
Debug.Indent();
glContext = new X11GLContext(mode, window); Debug.Print("Creating GameWindow with mode: {0}", mode.ToString());
//glContext.PrepareContext(window); Debug.Indent();
window.VisualInfo = (glContext.Info as X11.WindowInfo).VisualInfo;
// Create a window on this display using the visual above //glContext = new X11GLContext(mode, window);
Debug.Write("Opening render window... "); //glContext.PrepareContext(window);
//window.VisualInfo = (glContext.Info as X11.WindowInfo).VisualInfo;
//window.VisualInfo = Marshal.PtrToStructure(Glx.ChooseVisual(window.Display, window.Screen,
XSetWindowAttributes attributes = new XSetWindowAttributes(); // Create a window on this display using the visual above
attributes.background_pixel = IntPtr.Zero; Debug.Write("Opening render window... ");
attributes.border_pixel = IntPtr.Zero;
attributes.colormap = XSetWindowAttributes attributes = new XSetWindowAttributes();
API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/); attributes.background_pixel = IntPtr.Zero;
window.EventMask = attributes.border_pixel = IntPtr.Zero;
EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | attributes.colormap =
EventMask.KeyReleaseMask | EventMask.KeyPressMask;/* | API.CreateColormap(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.PointerMotionMask | /* Bad! EventMask.PointerMotionHintMask |
EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;*/ EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;*/
attributes.event_mask = (IntPtr)window.EventMask; attributes.event_mask = (IntPtr)window.EventMask;
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, ref attributes); (int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask, ref attributes);
if (window.Handle == IntPtr.Zero) if (window.Handle == IntPtr.Zero)
{ throw new ApplicationException("XCreateWindow call failed (returned 0).");
throw new ApplicationException("XCreateWindow call failed (returned 0).");
}
// 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 = mode.Width; hints.width = mode.Width;
hints.height = mode.Height; hints.height = mode.Height;
hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition); hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition);
Functions.XSetWMNormalHints(window.Display, window.Handle, ref hints); Functions.XSetWMNormalHints(window.Display, window.Handle, ref hints);
// Register for window destroy notification // Register for window destroy notification
IntPtr wm_destroy_atom = Functions.XInternAtom(window.Display, IntPtr wm_destroy_atom = Functions.XInternAtom(window.Display,
"WM_DELETE_WINDOW", true); "WM_DELETE_WINDOW", true);
XWMHints hint = new XWMHints(); XWMHints hint = new XWMHints();
Functions.XSetWMProtocols(window.Display, window.Handle, new IntPtr[] { wm_destroy_atom }, 1); Functions.XSetWMProtocols(window.Display, window.Handle, new IntPtr[] { wm_destroy_atom }, 1);
Top = Left = 0; Top = Left = 0;
Right = Width; Right = Width;
Bottom = Height; Bottom = Height;
//XTextProperty text = new XTextProperty(); //XTextProperty text = new XTextProperty();
//text.value = "OpenTK Game Window"; //text.value = "OpenTK Game Window";
//text.format = 8; //text.format = 8;
//Functions.XSetWMName(window.Display, window.Handle, ref text); //Functions.XSetWMName(window.Display, window.Handle, ref text);
//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.Handle); Debug.Print("done! (id: {0})", window.Handle);
(glContext.Info as X11.WindowInfo).Handle = window.Handle; //(glContext.Info as X11.WindowInfo).Handle = window.Handle;
glContext.CreateContext(true, null); //glContext.CreateContext(true, null);
glContext.MakeCurrent(); //glContext.MakeCurrent();
API.MapRaised(window.Display, window.Handle); API.MapRaised(window.Display, window.Handle);
mapped = true; mapped = true;
driver = new X11Input(window); driver = new X11Input(window);
//GL.LoadAll(); //GL.LoadAll();
//Glu.LoadAll(); //Glu.LoadAll();
Debug.Unindent(); Debug.Unindent();
Debug.WriteLine("GameWindow creation completed successfully!"); Debug.WriteLine("GameWindow creation completed successfully!");
exists = true; exists = true;
}
} }
#endregion #endregion
@ -612,8 +596,8 @@ namespace OpenTK.Platform.X11
{ {
if (manuallyCalled) if (manuallyCalled)
{ {
if (glContext != null) //if (glContext != null)
glContext.Dispose(); // glContext.Dispose();
// Kills connection to the X-Server. We don't want that, // Kills connection to the X-Server. We don't want that,
// 'cause it kills the ExampleLauncher too. // 'cause it kills the ExampleLauncher too.