Added OpenTK.Platform.WindowInfo and OpenTK.Platform.IMutableWindowInfo. Split IWindowInfo implementation to IWindowInfo and IMutableWindowInfo. Added several methods.

X11 and Windows GLControl and GLNative implementation now use IGLContext interfaces instead of direct X11GLContext and WinGLContext. Decouples the two (good!).
Updated all Native, Control, Context classes to use the new interfaces.
This commit is contained in:
the_fiddler 2007-09-09 15:10:21 +00:00
parent 2e572eb65a
commit 2ca6e6c617
12 changed files with 389 additions and 130 deletions

View file

@ -9,33 +9,30 @@ namespace OpenTK.Platform
/// </summary>
internal sealed class DummyGLContext : IGLContext
{
WindowInfo info = new WindowInfo();
DisplayMode mode = new DisplayMode();
#region --- IGLContext Members ---
public void SwapBuffers()
{
}
public IntPtr Context { get { return IntPtr.Zero; } }
public IWindowInfo Info { get { return info; } }
public DisplayMode Mode { get { return mode; } }
public void MakeCurrent()
{
}
public void CreateContext() { }
public void CreateContext(bool direct) { }
public void CreateContext(bool direct, IGLContext source) { }
public IntPtr GetAddress(string function)
{
return IntPtr.Zero;
}
public void SwapBuffers() { }
public void MakeCurrent() { }
public IEnumerable<DisplayMode> GetDisplayModes()
{
throw new Exception("The method or operation is not implemented.");
}
public IntPtr GetAddress(string function) { return IntPtr.Zero; }
public IEnumerable<DisplayMode> GetDisplayModes() { return null; }
#endregion
#region --- IDisposable Members ---
public void Dispose()
{
}
public void Dispose() { }
#endregion
}

View file

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Platform
{
public class GLContext : IGLContext
{
private IGLContext implementation;
public GLContext(DisplayMode mode, IWindowInfo window)
{
}
#region --- IGLContext Members ---
public IntPtr Context
{
get { return implementation.Context; }
}
public IWindowInfo Info
{
get { throw new Exception("The method or operation is not implemented."); }
}
public DisplayMode Mode
{
get { throw new Exception("The method or operation is not implemented."); }
}
public void CreateContext()
{
throw new Exception("The method or operation is not implemented.");
}
public void CreateContext(bool direct)
{
throw new Exception("The method or operation is not implemented.");
}
public void CreateContext(bool direct, IGLContext source)
{
throw new Exception("The method or operation is not implemented.");
}
public void SwapBuffers()
{
throw new Exception("The method or operation is not implemented.");
}
public void MakeCurrent()
{
throw new Exception("The method or operation is not implemented.");
}
public IntPtr GetAddress(string function)
{
throw new Exception("The method or operation is not implemented.");
}
public IEnumerable<DisplayMode> GetDisplayModes()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region IDisposable Members
public void Dispose()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
}
}

View file

@ -10,10 +10,59 @@ using System.Text;
namespace OpenTK.Platform
{
/// <summary>
/// Provides methods for creating and interacting with an OpenGL context.
/// </summary>
public interface IGLContext : IDisposable
{
/// <summary>
/// Swaps buffers on a context. This presents the rendered scene to the user.
/// Gets a handle to the OpenGL rendering context.
/// </summary>
IntPtr Context { get; }
/// <summary>
/// Gets the IWindowInfo describing the window associated with this context.
/// </summary>
IWindowInfo Info { get; }
/// <summary>
/// Gets the DisplayMode of the context.
/// </summary>
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>
/// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the
/// specified IGLContext.
/// </summary>
/// <param name="direct">Set to true for direct rendering or false otherwise.</param>
/// <param name="source">The source IGLContext to share state from.</param>.
/// <seealso cref="CreateContext(bool)"/>
void CreateContext(bool direct, IGLContext source);
/// <summary>
/// Swaps buffers on a context. This presents the rendered scene to the user.
/// </summary>
void SwapBuffers();

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Platform
{
/// <summary>
/// Provides methods to
/// </summary>
public interface IMutableWindowInfo : IWindowInfo
{
IWindowInfo GetInfoFrom(System.Windows.Forms.Control control);
IWindowInfo GetInfoFrom(System.Windows.Forms.NativeWindow window);
IWindowInfo GetInfoFrom(OpenTK.GameWindow window);
IWindowInfo GetInfoFrom(IWindowInfo info);
void CopyInfoFrom(IWindowInfo info);
}
}

View file

@ -18,9 +18,5 @@ namespace OpenTK.Platform
{
IntPtr Handle { 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

@ -8,9 +8,9 @@ namespace OpenTK.Platform
/// <summary>
/// Describes a Windows.Form.Control, Windows.Forms.NativeWindow or OpenTK.GameWindow.
/// </summary>
public sealed class WindowInfo : IWindowInfo
public sealed class WindowInfo : IMutableWindowInfo
{
IWindowInfo implementation;
IMutableWindowInfo implementation;
#region --- Constructors ---
@ -45,7 +45,7 @@ namespace OpenTK.Platform
/// <param name="control">The System.Windows.Forms.Control to get info from.</param>
public WindowInfo(Control control) : this()
{
implementation.GetInfoFrom(control);
implementation.CopyInfoFrom(implementation.GetInfoFrom(control));
}
/// <summary>
@ -86,40 +86,49 @@ namespace OpenTK.Platform
get { return implementation.Parent; }
}
#endregion
#region --- IMutableWindowInfo Members ---
/// <summary>
/// Updates the WindowInfo to describe the specified Control.
/// </summary>
/// <param name="control">The System.Windows.Forms.Control to describe.</param>
public void GetInfoFrom(Control control)
public IWindowInfo GetInfoFrom(Control control)
{
implementation.GetInfoFrom(control);
return implementation.GetInfoFrom(control);
}
/// <summary>
/// Updates the WindowInfo to describe the specified NativeWindow.
/// </summary>
/// <param name="window">The System.Windows.Forms.NativeWindow to describe.</param>
public void GetInfoFrom(NativeWindow window)
public IWindowInfo GetInfoFrom(NativeWindow window)
{
implementation.GetInfoFrom(window);
return implementation.GetInfoFrom(window);
}
/// <summary>
/// Updates the WindowInfo to describe the specified GameWindow.
/// </summary>
/// <param name="window">The OpenTK.GameWindow to describe.</param>
public void GetInfoFrom(GameWindow window)
public IWindowInfo GetInfoFrom(GameWindow window)
{
implementation.GetInfoFrom(window);
return implementation.GetInfoFrom(window);
}
/// <summary>
/// Updates the WindowInfo using the specified WindowInfo.
/// </summary>
/// <param name="window">The OpenTK.Platform.Window to get information from.</param>
public void GetInfoFrom(IWindowInfo info)
public IWindowInfo GetInfoFrom(IWindowInfo info)
{
implementation.GetInfoFrom(info);
return implementation.GetInfoFrom(info);
}
public void CopyInfoFrom(IWindowInfo info)
{
implementation.CopyInfoFrom(info);
}
#endregion

View file

@ -5,13 +5,17 @@
*/
#endregion
#region --- Using Directives ---
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using OpenTK.OpenGL;
using System.Diagnostics;
#endregion
namespace OpenTK.Platform.Windows
{
@ -24,7 +28,7 @@ namespace OpenTK.Platform.Windows
private IntPtr deviceContext;
private IntPtr renderContext;
static private IntPtr opengl32Handle;
static private readonly string opengl32Name = "OPENGL32.DLL";
private const string opengl32Name = "OPENGL32.DLL";
private WindowInfo windowInfo = new WindowInfo();
private DisplayMode mode;
@ -157,11 +161,59 @@ namespace OpenTK.Platform.Windows
Debug.Print("done! (format: {0})", pixel);
}
#endregion
#region --- IGLContext Members ---
#region public IntPtr Context
public IntPtr Context
{
get { return renderContext; }
private set { renderContext = value; }
}
#endregion
#region public IWindowInfo Info
public IWindowInfo Info
{
get { return windowInfo; }
}
#endregion
#region public DisplayMode Mode
public DisplayMode Mode
{
get { return new DisplayMode(mode); }
}
#endregion
#region public void CreateContext()
public void CreateContext()
{
this.CreateContext(true, null);
}
#endregion
#region public void CreateContext(bool direct)
public void CreateContext(bool direct)
{
this.CreateContext(direct, null);
}
#endregion
#region public void CreateContext(bool direct, IGLContext source)
public void CreateContext(bool direct, IGLContext source)
{
this.PrepareContext();
@ -175,16 +227,20 @@ namespace OpenTK.Platform.Windows
}
else
{
throw new ApplicationException("Could not create opengl Rendering Context.");
throw new ApplicationException("Could not create OpenGL render context (Wgl.CreateContext() return 0).");
}
Wgl.Imports.MakeCurrent(deviceContext, renderContext);
Wgl.LoadAll();
if (source != null)
{
Debug.Print("Sharing state with context {0}", (source as WinGLContext).Context);
Wgl.Imports.ShareLists(renderContext, (source as WinGLContext).Context);
}
}
#endregion
#region --- IGLContext Members ---
#region public void SwapBuffers()
public void SwapBuffers()

View file

@ -15,7 +15,7 @@ namespace OpenTK.Platform.Windows
/// 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.
/// </summary>
internal sealed class WindowInfo : IWindowInfo
internal sealed class WindowInfo : IMutableWindowInfo
{
private IntPtr handle;
private WindowInfo parent;
@ -24,6 +24,12 @@ namespace OpenTK.Platform.Windows
{
}
public WindowInfo(IntPtr handle, IWindowInfo parent)
{
this.Handle = handle;
this.Parent = parent;
}
public WindowInfo(IWindowInfo info)
{
if (info == null)
@ -77,51 +83,47 @@ namespace OpenTK.Platform.Windows
}
}
public void GetInfoFrom(Control control)
public IWindowInfo 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);
return new WindowInfo(control.Handle, null);
}
return new WindowInfo(control.Handle, GetInfoFrom(control.Parent));
}
public void GetInfoFrom(NativeWindow window)
public IWindowInfo GetInfoFrom(NativeWindow window)
{
if (window == null)
throw new ArgumentException("NativeWindow cannot be null.");
this.Handle = window.Handle;
this.Parent = null;
return new WindowInfo(window.Handle, null);
}
public void GetInfoFrom(GameWindow window)
public IWindowInfo 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;
return GetInfoFrom(window.WindowInfo as Windows.WindowInfo);
}
public void GetInfoFrom(IWindowInfo info)
public IWindowInfo GetInfoFrom(IWindowInfo info)
{
if (info == null)
throw new ArgumentException("IWindowInfo cannot be null.");
return info;
}
public void CopyInfoFrom(IWindowInfo info)
{
this.Handle = info.Handle;
this.Parent = info.Parent;
this.Parent = info.Parent;
}
#endregion

View file

@ -15,7 +15,7 @@ namespace OpenTK.Platform.X11
/// 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.
/// </summary>
internal sealed class WindowInfo : IWindowInfo
internal sealed class WindowInfo : IMutableWindowInfo
{
private IntPtr rootWindow, handle, topLevelWindow, display;
private int screen;
@ -49,7 +49,14 @@ namespace OpenTK.Platform.X11
#region --- IWindowInfo Members ---
public void GetInfoFrom(Control control)
public IntPtr Handle { get { return handle; } internal set { handle = value; } }
public IWindowInfo Parent { get { return parent; } internal set { parent = value as WindowInfo; } }
#endregion
#region --- IMutableWindowInfo Members ---
public IWindowInfo GetInfoFrom(Control control)
{
if (control == null)
throw new ArgumentException("GameWindow cannot be null.");
@ -57,7 +64,7 @@ namespace OpenTK.Platform.X11
throw new NotImplementedException();
}
public void GetInfoFrom(NativeWindow window)
public IWindowInfo GetInfoFrom(NativeWindow window)
{
if (window == null)
throw new ArgumentException("GameWindow cannot be null.");
@ -65,24 +72,29 @@ namespace OpenTK.Platform.X11
throw new NotImplementedException();
}
public void GetInfoFrom(GameWindow window)
public IWindowInfo GetInfoFrom(GameWindow window)
{
if (window == null)
throw new ArgumentException("GameWindow cannot be null.");
this.GetInfoFrom(window.WindowInfo as X11.WindowInfo);
return this.GetInfoFrom(window.WindowInfo as X11.WindowInfo);
}
public void GetInfoFrom(IWindowInfo info)
public IWindowInfo GetInfoFrom(IWindowInfo info)
{
if (info == null)
throw new ArgumentException("WindowInfo cannot be null");
WindowInfo winfo = info as WindowInfo;
return info;
}
public void CopyInfoFrom(IWindowInfo info)
{
this.Handle = info.Handle;
this.Parent = info.Parent;
WindowInfo winfo = info as WindowInfo;
this.RootWindow = winfo.RootWindow;
this.TopLevelWindow = winfo.TopLevelWindow;
this.Display = winfo.Display;
@ -90,9 +102,6 @@ namespace OpenTK.Platform.X11
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; } }

View file

@ -37,7 +37,7 @@ namespace OpenTK.Platform.X11
{
}
internal X11GLContext(DisplayMode mode, IWindowInfo info)
public X11GLContext(DisplayMode mode, IWindowInfo info)
{
if (info == null)
throw new ArgumentException("IWindowInfo cannot be null.");
@ -49,44 +49,24 @@ namespace OpenTK.Platform.X11
#endregion
#region internal XVisualInfo VisualInfo
//#region private XVisualInfo VisualInfo
internal XVisualInfo VisualInfo
{
get { return windowInfo.VisualInfo; }
}
//private XVisualInfo VisualInfo
//{
// get { return windowInfo.VisualInfo; }
//}
#endregion
//#endregion
#region internal IntPtr Handle
//#region private IntPtr Handle
internal IntPtr Handle
{
get { return windowInfo.Handle; }
set { windowInfo.Handle = value; }
}
//private IntPtr Handle
//{
// get { return windowInfo.Handle; }
// set { windowInfo.Handle = value; }
//}
#endregion
#region internal DisplayMode Mode
internal DisplayMode Mode
{
get { return mode; }
set
{
if (context == IntPtr.Zero)
{
mode = value;
}
else
{
Debug.Print("Cannot change DisplayMode of an existing context.");
}
}
}
#endregion
//#endregion
#region private void PrepareContext()
@ -138,34 +118,98 @@ namespace OpenTK.Platform.X11
#endregion
#region internal void CreateContext(X11GLContext shareContext, bool direct)
#region --- IGLContext Members ---
internal void CreateContext(X11GLContext shareContext, bool direct)
#region public IntPtr Context
public IntPtr Context
{
Debug.WriteLine("Creating opengl context.");
Debug.Indent();
get { return context; }
private set { context = value; }
}
IntPtr shareHandle = shareContext != null ? shareContext.windowInfo.Handle : IntPtr.Zero;
Debug.WriteLine(shareHandle == IntPtr.Zero ? "Context is not shared." :
String.Format("Context is shared with context: {0}", shareHandle));
#endregion
Debug.WriteLine(direct ? "Context is direct." : "Context is indirect.");
#region public DisplayMode Mode
context = Glx.CreateContext(windowInfo.Display, visual, shareHandle, direct);
Debug.Unindent();
if (context != IntPtr.Zero)
public DisplayMode Mode
{
get { return mode; }
private set
{
Debug.WriteLine(String.Format("New opengl context created. (id: {0})", context));
}
else
{
throw new ApplicationException("Glx.CreateContext call failed (returned 0).");
if (context == IntPtr.Zero)
{
mode = value;
}
else
{
Debug.Print("Cannot change DisplayMode of an existing context.");
}
}
}
#endregion
#region --- IGLContext Members ---
#region public IWindowInfo Info
public IWindowInfo Info { get { return windowInfo; } }
#endregion
public void CreateContext()
{
this.CreateContext(true, null);
}
public void CreateContext(bool direct)
{
this.CreateContext(direct, null);
}
#region public void CreateContext(bool direct, IGLContext shareContext)
public void CreateContext(bool direct, IGLContext shareContext)
{
try
{
Debug.WriteLine("Creating opengl context.");
Debug.Indent();
IntPtr shareHandle = shareContext != null ? (shareContext as X11GLContext).Context: IntPtr.Zero;
Debug.Write(direct ? "Context is direct, " : "Context is indirect, ");
Debug.WriteLine(shareHandle == IntPtr.Zero ? "not shared." :
String.Format("shared with ({0}).", shareHandle));
// Try to call Glx.CreateContext with the specified parameters.
context = Glx.CreateContext(windowInfo.Display, visual, shareHandle, direct);
// Context creation succeeded, return.
if (context != IntPtr.Zero)
{
Debug.Print("New opengl context created. (id: {0})", context);
return;
}
// Context creation failed. Retry with a non-shared context with the
// direct/indirect rendering mode flipped.
Debug.Print("Cotnext creation failed, retrying with a non-shared, {0} context.",
!direct ? "direct" : "indirect");
context = Glx.CreateContext(windowInfo.Display, visual, IntPtr.Zero, !direct);
if (context != IntPtr.Zero)
{
Debug.Print("New opengl context created. (id: {0})", context);
return;
}
throw new ApplicationException("Glx.CreateContext call failed (returned 0).");
}
finally
{
Debug.Unindent();
}
}
#endregion
#region public void SwapBuffers()

View file

@ -18,7 +18,7 @@ namespace OpenTK.Platform.X11
WindowInfo info = new WindowInfo();
//DisplayMode mode;
private Type xplatui;
X11GLContext glContext;
IGLContext glContext;
private bool disposed;
private bool fullscreen;
@ -55,10 +55,10 @@ namespace OpenTK.Platform.X11
Debug.Print("Data read from System.Windows.Forms.XplatUIX11: {0}", info.ToString());
//this.mode = mode;
glContext = new X11GLContext(null, info);
glContext = new GLContext(null, info);
//glContext.PrepareContext(info);
info.VisualInfo = glContext.VisualInfo;
info.VisualInfo = (glContext.Info as X11.WindowInfo).VisualInfo;
Debug.Print("Setting XplatUIX11.CustomVisual");
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
@ -83,8 +83,8 @@ namespace OpenTK.Platform.X11
try
{
glContext.Handle = info.Handle = (sender as UserControl).Handle;
glContext.CreateContext(null, true);
(glContext.Info as X11.WindowInfo).Handle = info.Handle = (sender as UserControl).Handle;
glContext.CreateContext(true, null);
glContext.MakeCurrent();
}
catch (ApplicationException expt)
@ -128,7 +128,8 @@ namespace OpenTK.Platform.X11
return Functions.XDefaultColormap(info.Display, info.Screen);
}
return API.CreateColormap(info.Display, info.RootWindow, glContext.VisualInfo.visual, 0/*AllocNone*/);
return API.CreateColormap(info.Display, info.RootWindow,
(glContext.Info as X11.WindowInfo).VisualInfo.visual, 0/*AllocNone*/);
}
#endregion

View file

@ -257,7 +257,7 @@ namespace OpenTK.Platform.X11
glContext = new X11GLContext(mode, window);
//glContext.PrepareContext(window);
window.VisualInfo = glContext.VisualInfo;
window.VisualInfo = (glContext.Info as X11.WindowInfo).VisualInfo;
// Create a window on this display using the visual above
Debug.Write("Opening render window... ");
@ -303,9 +303,8 @@ namespace OpenTK.Platform.X11
Debug.Print("done! (id: {0})", window.Handle);
glContext.Handle = window.Handle;
glContext.CreateContext(null, true);
(glContext.Info as X11.WindowInfo).Handle = window.Handle;
glContext.CreateContext(true, null);
glContext.MakeCurrent();
API.MapRaised(window.Display, window.Handle);