Decoupled GLContext from GLControl/GameWindow even more, by using IWindowInfo to pass data between them.

Implemented the IWindowInfo.GetInfoFrom methods.
Removed said methods from OpenTK/Platform/Utilities.
This commit is contained in:
the_fiddler 2007-09-09 11:52:09 +00:00
parent e0c514f96e
commit c1fa34087c
10 changed files with 291 additions and 103 deletions

View file

@ -11,11 +11,16 @@ using System.Text;
namespace OpenTK.Platform namespace OpenTK.Platform
{ {
/// <summary> /// <summary>
/// This interface supports OpenTK, and is not intended for use by OpenTK programs. /// Provides a platform independent mechanism to interact with System.Windows.Forms.Control,
/// System.Windows.Forms.NativeWindow and OpenTK.GameWindow low-level implementation data.
/// </summary> /// </summary>
public interface IWindowInfo public interface IWindowInfo
{ {
IntPtr Handle { get; } IntPtr Handle { get; }
IWindowInfo Parent { get; } IWindowInfo Parent { get; }
void GetInfoFrom(System.Windows.Forms.Control control);
void GetInfoFrom(System.Windows.Forms.NativeWindow window);
void GetInfoFrom(OpenTK.GameWindow window);
void GetInfoFrom(IWindowInfo info);
} }
} }

View file

@ -82,11 +82,6 @@ namespace OpenTK.Platform
private static Platform platform = Platform.Unknown; private static Platform platform = Platform.Unknown;
public static IWindowInfo GetWindowInfo(Form form)
{
throw new NotImplementedException();
}
#region public static IntPtr GetAddress(string function) #region public static IntPtr GetAddress(string function)
/// <summary> /// <summary>

View file

@ -13,16 +13,19 @@ using System.Runtime.InteropServices;
using OpenTK.OpenGL; using OpenTK.OpenGL;
using System.Diagnostics; using System.Diagnostics;
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
public sealed class WinGLContext : OpenTK.Platform.IGLContext, IDisposable /// <summary>
/// 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.
/// </summary>
internal sealed class WinGLContext : OpenTK.Platform.IGLContext, IDisposable
{ {
private IntPtr deviceContext; private IntPtr deviceContext;
private IntPtr renderContext; private IntPtr renderContext;
static private IntPtr opengl32Handle; static private IntPtr opengl32Handle;
static private readonly string opengl32Name = "OPENGL32.DLL"; static private readonly string opengl32Name = "OPENGL32.DLL";
private IntPtr windowHandle; private WindowInfo windowInfo = new WindowInfo();
private DisplayMode mode; private DisplayMode mode;
@ -30,25 +33,33 @@ namespace OpenTK.Platform.Windows
#region --- Contructors --- #region --- Contructors ---
public WinGLContext() internal WinGLContext()
: this(new DisplayMode(640, 480, new ColorMode(32), 16, 0, 0, 2, false, false, false, 0.0f)) : this(new DisplayMode(640, 480))
{ {
} }
public WinGLContext(DisplayMode mode) internal WinGLContext(DisplayMode mode)
{ {
Trace.WriteLine(String.Format("Creating opengl context (driver: {0})", this.ToString())); //Trace.WriteLine(String.Format("Creating opengl context (driver: {0})", this.ToString()));
this.mode = mode;
}
public WinGLContext(DisplayMode mode, IWindowInfo info)
{
this.windowInfo = info as WindowInfo;
this.mode = mode; this.mode = mode;
} }
#endregion #endregion
#region public void PrepareContext(IntPtr handle) #region private void PrepareContext()
public void PrepareContext(IntPtr handle) private void PrepareContext()
{ {
this.windowHandle = handle; if (this.windowInfo.Handle == IntPtr.Zero)
Debug.WriteLine(String.Format("OpenGL context is bound to handle: {0}", windowHandle)); throw new ApplicationException("No Window Handle specified for opengl context.");
Debug.WriteLine(String.Format("OpenGL context is bound to handle: {0}", this.windowInfo.Handle));
// Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl. // Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl.
if (opengl32Handle == IntPtr.Zero) if (opengl32Handle == IntPtr.Zero)
@ -68,7 +79,7 @@ namespace OpenTK.Platform.Windows
Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle)); Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle));
} }
deviceContext = API.GetDC(windowHandle); deviceContext = API.GetDC(this.windowInfo.Handle);
Debug.WriteLine(String.Format("Device context: {0}", deviceContext)); Debug.WriteLine(String.Format("Device context: {0}", deviceContext));
Debug.Write("Setting pixel format... "); Debug.Write("Setting pixel format... ");
@ -152,6 +163,8 @@ namespace OpenTK.Platform.Windows
public void CreateContext() public void CreateContext()
{ {
this.PrepareContext();
Debug.Write("Creating render context... "); Debug.Write("Creating render context... ");
// 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.
@ -302,7 +315,7 @@ namespace OpenTK.Platform.Windows
if (deviceContext != IntPtr.Zero) if (deviceContext != IntPtr.Zero)
{ {
if (!API.ReleaseDC(windowHandle, deviceContext)) if (!API.ReleaseDC(this.windowInfo.Handle, deviceContext))
{ {
//throw new ApplicationException("Could not release device context. Error: " + Marshal.GetLastWin32Error()); //throw new ApplicationException("Could not release device context. Error: " + Marshal.GetLastWin32Error());
//Debug.Print("Could not destroy the device context. Error: {0}", Marshal.GetLastWin32Error()); //Debug.Print("Could not destroy the device context. Error: {0}", Marshal.GetLastWin32Error());

View file

@ -35,8 +35,6 @@ namespace OpenTK.Platform.Windows
c.HandleCreated += new EventHandler(c_HandleCreated); c.HandleCreated += new EventHandler(c_HandleCreated);
c.HandleDestroyed += new EventHandler(c_HandleDestroyed); c.HandleDestroyed += new EventHandler(c_HandleDestroyed);
glContext = new WinGLContext(mode);
} }
#endregion #endregion
@ -48,7 +46,10 @@ namespace OpenTK.Platform.Windows
try try
{ {
glContext.PrepareContext((sender as Control).Handle); if (glContext != null)
glContext.Dispose();
glContext = new WinGLContext(mode, new WindowInfo(sender as Control));
glContext.CreateContext(); glContext.CreateContext();
glContext.MakeCurrent(); glContext.MakeCurrent();
} }

View file

@ -215,6 +215,7 @@ namespace OpenTK.Platform.Windows
public IWindowInfo WindowInfo public IWindowInfo WindowInfo
{ {
get { return window; } get { return window; }
private set { window = value as WindowInfo; }
} }
#endregion #endregion
@ -287,16 +288,14 @@ namespace OpenTK.Platform.Windows
public void OnCreate(EventArgs e) public void OnCreate(EventArgs e)
{ {
window = new WindowInfo(); this.WindowInfo = new WindowInfo(this);
window.Handle = this.Handle;
window.Parent = null;
Debug.Print("Window created: {0}", window); Debug.Print("Window created: {0}", window);
try try
{ {
glContext = new WinGLContext(this.mode); glContext = new WinGLContext(this.mode, this.WindowInfo);
glContext.PrepareContext(this.Handle); //glContext.PrepareContext(this.Handle);
glContext.CreateContext(); glContext.CreateContext();
//glContext.MakeCurrent(); //glContext.MakeCurrent();
GL.LoadAll(); GL.LoadAll();

View file

@ -7,18 +7,59 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Windows.Forms;
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
/// <summary> /// <summary>
/// Describes a Windows window. /// Describes a Windows.Form.Control, Windows.Forms.NativeWindow or OpenTK.GameWindow 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 class WindowInfo : IWindowInfo internal sealed class WindowInfo : IWindowInfo
{ {
private IntPtr handle; private IntPtr handle;
private WindowInfo parent; private WindowInfo parent;
public WindowInfo()
{
}
public WindowInfo(IWindowInfo info)
{
if (info == null)
throw new ArgumentException("WindowInfo cannot be null.");
this.Handle = info.Handle;
this.Parent = info.Parent;
}
public WindowInfo(Control control)
{
if (control == null)
throw new ArgumentException("Control cannot be null.");
this.Handle = control.Handle;
this.Parent = control.Parent != null ? new WindowInfo(control.Parent) : this.Parent;
}
public WindowInfo(NativeWindow window)
{
if (window == null)
throw new ArgumentException("NativeWindow cannot be null.");
this.Handle = window.Handle;
this.Parent = null;
}
public WindowInfo(GameWindow window)
{
if (window == null)
throw new ArgumentException("GameWindow cannot be null.");
this.Handle = window.WindowInfo.Handle;
this.Parent = window.WindowInfo.Parent;
}
#region --- IWindowInfo Members --- #region --- IWindowInfo Members ---
public IntPtr Handle public IntPtr Handle
@ -30,7 +71,57 @@ namespace OpenTK.Platform.Windows
public IWindowInfo Parent public IWindowInfo Parent
{ {
get { return parent; } get { return parent; }
internal set { parent = value as WindowInfo; } internal set
{
parent = value as WindowInfo;
}
}
public void GetInfoFrom(Control control)
{
if (control == null)
throw new ArgumentException("Control cannot be null.");
this.Handle = control.Handle;
if (control.Parent == null)
{
this.Parent = null;
}
else
{
if (this.Parent == null)
this.Parent = new WindowInfo(control.Parent);
else
this.Parent.GetInfoFrom(control.Parent);
}
}
public void GetInfoFrom(NativeWindow window)
{
if (window == null)
throw new ArgumentException("NativeWindow cannot be null.");
this.Handle = window.Handle;
this.Parent = null;
}
public void GetInfoFrom(GameWindow window)
{
if (window == null)
throw new ArgumentException("GameWindow cannot be null.");
WindowInfo info = (window.WindowInfo as Windows.WindowInfo);
this.Handle = info.Handle;
this.Parent = info.Parent;
}
public void GetInfoFrom(IWindowInfo info)
{
if (info == null)
throw new ArgumentException("IWindowInfo cannot be null.");
this.Handle = info.Handle;
this.Parent = info.Parent;
} }
#endregion #endregion
@ -40,6 +131,5 @@ namespace OpenTK.Platform.Windows
return String.Format("Windows.WindowInfo: Handle {0}, Parent ({1})", return String.Format("Windows.WindowInfo: Handle {0}, Parent ({1})",
this.Handle, this.Parent != null ? this.Parent.ToString() : "null"); this.Handle, this.Parent != null ? this.Parent.ToString() : "null");
} }
} }
} }

View file

@ -7,44 +7,99 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Windows.Forms;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
{ {
/// <summary> /// <summary>
/// Describes an X11 window. /// Describes a Windows.Form.Control, Windows.Forms.NativeWindow or OpenTK.GameWindow 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>
public class WindowInfo : IWindowInfo internal sealed class WindowInfo : IWindowInfo
{ {
public WindowInfo()
{
visinfo = new XVisualInfo();
}
public WindowInfo(WindowInfo parent)
{
this.Handle = parent.Handle;
this.TopLevelWindow = parent.TopLevelWindow;
this.Screen = parent.Screen;
this.Display = parent.Display;
this.RootWindow = parent.RootWindow;
this.VisualInfo = parent.VisualInfo;
this.Parent = parent;
}
private IntPtr rootWindow, handle, topLevelWindow, display; private IntPtr rootWindow, handle, topLevelWindow, display;
private int screen; private int screen;
private WindowInfo parent; private WindowInfo parent;
private XVisualInfo visinfo; private XVisualInfo visinfo;
public IntPtr RootWindow { get { return rootWindow; } set { rootWindow = value; } } public WindowInfo()
public IntPtr TopLevelWindow { get { return topLevelWindow; } set { topLevelWindow = value; } } {
public IntPtr Display { get { return display; } set { display = value; } } visinfo = new XVisualInfo();
public int Screen { get { return screen; } set { screen = value; } } }
public XVisualInfo VisualInfo { get { return visinfo; } set { visinfo = value; } }
public IntPtr Handle { get { return handle; } set { handle = value; } } public WindowInfo(Control control)
public IWindowInfo Parent { get { return parent; } set { parent = value as WindowInfo; } } {
throw new NotImplementedException();
}
public WindowInfo(NativeWindow window)
{
throw new NotImplementedException();
}
public WindowInfo(GameWindow window)
{
throw new NotImplementedException();
}
public WindowInfo(WindowInfo info)
{
this.GetInfoFrom(info);
}
#region --- IWindowInfo Members ---
public void GetInfoFrom(Control control)
{
if (control == null)
throw new ArgumentException("GameWindow cannot be null.");
throw new NotImplementedException();
}
public void GetInfoFrom(NativeWindow window)
{
if (window == null)
throw new ArgumentException("GameWindow cannot be null.");
throw new NotImplementedException();
}
public void GetInfoFrom(GameWindow window)
{
if (window == null)
throw new ArgumentException("GameWindow cannot be null.");
this.GetInfoFrom(window.WindowInfo as X11.WindowInfo);
}
public void GetInfoFrom(IWindowInfo info)
{
if (info == null)
throw new ArgumentException("WindowInfo cannot be null");
WindowInfo winfo = info as WindowInfo;
this.Handle = info.Handle;
this.Parent = info.Parent;
this.RootWindow = winfo.RootWindow;
this.TopLevelWindow = winfo.TopLevelWindow;
this.Display = winfo.Display;
this.Screen = winfo.Screen;
this.VisualInfo = winfo.VisualInfo;
}
public IntPtr Handle { get { return handle; } internal set { handle = value; } }
public IWindowInfo Parent { get { return parent; } internal set { parent = value as WindowInfo; } }
#endregion
public IntPtr RootWindow { get { return rootWindow; } internal set { rootWindow = value; } }
public IntPtr TopLevelWindow { get { return topLevelWindow; } internal set { topLevelWindow = value; } }
public IntPtr Display { get { return display; } internal set { display = value; } }
public int Screen { get { return screen; } internal set { screen = value; } }
public XVisualInfo VisualInfo { get { return visinfo; } internal set { visinfo = value; } }
public override string ToString() public override string ToString()
{ {

View file

@ -15,29 +15,55 @@ using OpenTK.OpenGL;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
{ {
/// <summary> /// <summary>
/// Provides methods to create and control an opengl context on X11. /// 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.
/// </summary> /// </summary>
public sealed class X11GLContext : OpenTK.Platform.IGLContext internal sealed class X11GLContext : OpenTK.Platform.IGLContext
{ {
private IntPtr context; private IntPtr context;
private DisplayMode mode; private DisplayMode mode;
internal WindowInfo windowInfo; private WindowInfo windowInfo;
private IntPtr visual;
internal IntPtr visual;
private bool disposed; private bool disposed;
#region --- Public Constructor --- #region --- Constructors ---
internal X11GLContext() internal X11GLContext() : this(new DisplayMode(), new WindowInfo())
: this(new DisplayMode())
{ {
} }
internal X11GLContext(DisplayMode mode) internal X11GLContext(DisplayMode mode) : this(mode, new WindowInfo())
{ {
this.windowInfo = new WindowInfo(); }
internal X11GLContext(DisplayMode mode, IWindowInfo info)
{
if (info == null)
throw new ArgumentException("IWindowInfo cannot be null.");
this.windowInfo = info as WindowInfo;
this.mode = mode; this.mode = mode;
this.ChooseContext();
}
#endregion
#region internal XVisualInfo VisualInfo
internal XVisualInfo VisualInfo
{
get { return windowInfo.VisualInfo; }
}
#endregion
#region internal IntPtr Handle
internal IntPtr Handle
{
get { return windowInfo.Handle; }
set { windowInfo.Handle = value; }
} }
#endregion #endregion
@ -62,12 +88,10 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region internal void PrepareContext(X11.WindowInfo info) #region private void PrepareContext()
internal void PrepareContext(X11.WindowInfo info) private void ChooseContext()
{ {
this.windowInfo = new WindowInfo(info);
List<int> visualAttributes = new List<int>(); List<int> visualAttributes = new List<int>();
if (mode == null) if (mode == null)

View file

@ -25,6 +25,8 @@ namespace OpenTK.Platform.X11
#region --- Contructors --- #region --- Contructors ---
#region public X11GLControl(UserControl c)
public X11GLControl(UserControl c) public X11GLControl(UserControl c)
{ {
Debug.WriteLine("Creating opengl control (X11GLControl driver)"); Debug.WriteLine("Creating opengl control (X11GLControl driver)");
@ -37,44 +39,42 @@ namespace OpenTK.Platform.X11
throw new ArgumentException("UserControl c may not be null."); throw new ArgumentException("UserControl c may not be null.");
} }
//this.mode = mode;
glContext = new X11GLContext(null);
c.HandleCreated += new EventHandler(c_HandleCreated); c.HandleCreated += new EventHandler(c_HandleCreated);
c.HandleDestroyed += new EventHandler(c_HandleDestroyed); c.HandleDestroyed += new EventHandler(c_HandleDestroyed);
xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
Debug.Write("System.Windows.Forms.XplatUIX11: "); if (xplatui == null)
throw new ApplicationException("Could not get System.Windows.Forms.XplatUIX11 through reflection. Unsupported platform or Mono runtime version, aborting.");
info.Display = (IntPtr)xplatui.GetField("DisplayHandle",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
info.RootWindow = (IntPtr)xplatui.GetField("RootWindow",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
info.Screen = (int)xplatui.GetField("ScreenNo",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
Debug.Print("Data read from System.Windows.Forms.XplatUIX11: {0}", info.ToString());
if (xplatui != null) //this.mode = mode;
{ glContext = new X11GLContext(null, info);
info.Display = (IntPtr)xplatui.GetField("DisplayHandle", //glContext.PrepareContext(info);
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
info.VisualInfo = glContext.VisualInfo;
info.RootWindow = (IntPtr)xplatui.GetField("RootWindow", Debug.Print("Setting XplatUIX11.CustomVisual");
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, info.VisualInfo.visual);
info.Screen = (int)xplatui.GetField("ScreenNo", Debug.Print("Setting XplatUIX11.CustomColormap");
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, API.CreateColormap(info.Display, info.RootWindow, info.VisualInfo.visual, 0));
Debug.Print("Display: {0}, Screen: {1}, Root Window: {2}, GLControl: {3}",
info.Display, info.Screen, info.RootWindow, info.Handle);
glContext.PrepareContext(info);
info.VisualInfo = glContext.windowInfo.VisualInfo;
Debug.Print("Setting XplatUIX11.CustomVisual");
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, info.VisualInfo.visual);
Debug.Print("Setting XplatUIX11.CustomColormap");
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, API.CreateColormap(info.Display, info.RootWindow, info.VisualInfo.visual, 0));
}
Debug.Unindent(); Debug.Unindent();
} }
#endregion
#region void c_HandleCreated(object sender, EventArgs e)
void c_HandleCreated(object sender, EventArgs e) void c_HandleCreated(object sender, EventArgs e)
{ {
UserControl c = (sender as UserControl); UserControl c = (sender as UserControl);
@ -83,7 +83,7 @@ namespace OpenTK.Platform.X11
try try
{ {
glContext.windowInfo.Handle = info.Handle = (sender as UserControl).Handle; glContext.Handle = info.Handle = (sender as UserControl).Handle;
glContext.CreateContext(null, true); glContext.CreateContext(null, true);
glContext.MakeCurrent(); glContext.MakeCurrent();
} }
@ -98,12 +98,18 @@ namespace OpenTK.Platform.X11
} }
} }
#endregion
#region void c_HandleDestroyed(object sender, EventArgs e)
void c_HandleDestroyed(object sender, EventArgs e) void c_HandleDestroyed(object sender, EventArgs e)
{ {
Debug.Print("X11GLControl handle destroyed, disposing X11GLContext."); Debug.Print("X11GLControl handle destroyed, disposing X11GLContext.");
glContext.Dispose(); glContext.Dispose();
} }
#endregion
#region private IntPtr FindColormap() #region private IntPtr FindColormap()
/// <summary> /// <summary>
@ -122,7 +128,7 @@ namespace OpenTK.Platform.X11
return Functions.XDefaultColormap(info.Display, info.Screen); return Functions.XDefaultColormap(info.Display, info.Screen);
} }
return API.CreateColormap(info.Display, info.RootWindow, glContext.windowInfo.VisualInfo.visual, 0/*AllocNone*/); return API.CreateColormap(info.Display, info.RootWindow, glContext.VisualInfo.visual, 0/*AllocNone*/);
} }
#endregion #endregion

View file

@ -255,9 +255,9 @@ namespace OpenTK.Platform.X11
Debug.Print("Display: {0}, Screen {1}, Root window: {2}", Debug.Print("Display: {0}, Screen {1}, Root window: {2}",
window.Display, window.Screen, window.RootWindow); window.Display, window.Screen, window.RootWindow);
glContext = new X11GLContext(mode); glContext = new X11GLContext(mode, window);
glContext.PrepareContext(window); //glContext.PrepareContext(window);
window.VisualInfo = glContext.windowInfo.VisualInfo; window.VisualInfo = glContext.VisualInfo;
// Create a window on this display using the visual above // Create a window on this display using the visual above
Debug.Write("Opening render window... "); Debug.Write("Opening render window... ");
@ -303,7 +303,7 @@ namespace OpenTK.Platform.X11
Debug.Print("done! (id: {0})", window.Handle); Debug.Print("done! (id: {0})", window.Handle);
glContext.windowInfo.Handle = window.Handle; glContext.Handle = window.Handle;
glContext.CreateContext(null, true); glContext.CreateContext(null, true);
glContext.MakeCurrent(); glContext.MakeCurrent();