Renamed internal BindingsBase.LoadAll/Load methods to LoadEntryPoints/LoadEntryPoint, in order to avoid name clashes with the static GL.LoadAll() method.

Added GraphicsContext() constructor that takes an existing, valid OpenGL context. This can be used for interop with third-party toolkits which create the OpenGL context themselves.
This commit is contained in:
the_fiddler 2009-11-04 16:49:56 +00:00
parent b3c66b852d
commit 2d4b962d2c
14 changed files with 125 additions and 294 deletions

View file

@ -123,9 +123,9 @@ namespace OpenTK
#region Internal Members
#region LoadAll
#region LoadEntryPoints
internal void LoadAll()
internal void LoadEntryPoints()
{
// Using reflection is more than 3 times faster than directly loading delegates on the first
// run, probably due to code generation overhead. Subsequent runs are faster with direct loading
@ -164,12 +164,9 @@ namespace OpenTK
#endregion
#region Load
#region LoadEntryPoint
/// <summary>
/// Loads all extension and core functions.
/// </summary>
internal bool Load(string function)
internal bool LoadEntryPoint(string function)
{
FieldInfo f = DelegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)

View file

@ -27,7 +27,7 @@ namespace OpenTK.Graphics
// Indicates that this context was created through external means, e.g. Tao.Sdl or GLWidget#.
// In this case, We'll assume that the external program will manage the lifetime of this
// context - we'll not destroy it manually.
//bool is_external;
readonly bool IsExternal;
bool check_errors = true;
static bool share_contexts = true;
@ -101,17 +101,8 @@ namespace OpenTK.Graphics
Debug.Print("GraphicsContextFlags: {0}", flags);
Debug.Print("Requested version: {0}.{1}", major, minor);
IGraphicsContext shareContext = null;
if (GraphicsContext.ShareContexts)
{
// A small hack to create a shared context with the first available context.
foreach (WeakReference r in GraphicsContext.available_contexts.Values)
{
shareContext = (IGraphicsContext)r.Target;
break;
}
}
IGraphicsContext shareContext = shareContext = FindSharedContext();
// Todo: Add a DummyFactory implementing IPlatformFactory.
if (designMode)
implementation = new Platform.Dummy.DummyGLContext();
@ -131,6 +122,50 @@ namespace OpenTK.Graphics
}
}
public GraphicsContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags)
{
lock (SyncRoot)
{
IsExternal = true;
if (handle == ContextHandle.Zero)
{
implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle);
}
else if (available_contexts.ContainsKey(handle))
{
throw new GraphicsContextException("Context already exists.");
}
else
{
switch ((flags & GraphicsContextFlags.Embedded) == GraphicsContextFlags.Embedded)
{
case false: implementation = Factory.Default.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break;
case true: implementation = Factory.Embedded.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break;
}
}
available_contexts.Add((implementation as IGraphicsContextInternal).Context, new WeakReference(this));
}
}
#endregion
#region Private Members
static IGraphicsContext FindSharedContext()
{
if (GraphicsContext.ShareContexts)
{
// A small hack to create a shared context with the first available context.
foreach (WeakReference r in GraphicsContext.available_contexts.Values)
{
return (IGraphicsContext)r.Target;
}
}
return null;
}
#endregion
#region --- Static Members ---
@ -420,7 +455,7 @@ namespace OpenTK.Graphics
available_contexts.Remove((this as IGraphicsContextInternal).Context);
}
if (manual)
if (manual && !IsExternal)
{
if (implementation != null)
implementation.Dispose();
@ -429,11 +464,6 @@ namespace OpenTK.Graphics
}
}
//~GraphicsContext()
//{
// this.Dispose(false);
//}
#endregion
}
}

View file

@ -66,276 +66,18 @@ namespace OpenTK.Graphics.OpenGL
#endregion
#region --- Public Members ---
#if false
#region public static bool SupportsExtension(string name)
/// <summary>
/// Determines whether the specified OpenGL extension category is available in
/// the current OpenGL context. Equivalent to IsExtensionSupported(name, true)
/// Loads all OpenGL entry points (core and extension).
/// This method is provided for compatibility purposes with older OpenTK versions.
/// </summary>
/// <param name="name">The string for the OpenGL extension category (eg. "GL_ARB_multitexture")</param>
/// <returns>True if the specified extension is available, false otherwise.</returns>
public static bool SupportsExtension(string name)
public static void LoadAll()
{
if (RebuildExtensionList)
BuildExtensionList();
lock (gl_lock)
{
sb.Remove(0, sb.Length);
if (!name.StartsWith("GL_"))
sb.Append("gl_");
sb.Append(name.ToLower());
sb.Replace("_", String.Empty);
// Search the cache for the string.
return AvailableExtensions.ContainsKey(sb.ToString());
}
new GL().LoadEntryPoints();
}
#endregion
#region public static Delegate GetDelegate(string name)
/// <summary>
/// Returns a System.Delegate wrapping the specified OpenGL function. You must use the
/// base OpenGL name of the function (e.g. "glVertex3fv" instead of "Vertex3").
/// </summary>
/// <param name="name">The name of the OpenGL function (eg. "glNewList")</param>
/// <returns>
/// A System.Delegate that can be used to call this OpenGL function or null, if the specified
/// function name does not correspond to an OpenGL function or if the function is not
/// supported by the video drivers.
/// </returns>
public static Delegate GetDelegate(string name)
{
FieldInfo info = typeof(Delegates).GetField(name, BindingFlags.Static | BindingFlags.NonPublic);
if (info == null)
return null;
return (Delegate)info.GetValue(null);
}
#endregion
#region public static bool SupportsFunction(string function)
/// <summary>
/// Checks if a given OpenGL function is supported by the current context
/// </summary>
/// <param name="function">The name of the OpenGL function (i.e. glShaderSource)</param>
/// <returns>True if the function is supported, false otherwise</returns>
public static bool SupportsFunction(string function)
{
lock (gl_lock)
{
if (function == null)
throw new ArgumentNullException("function");
sb.Remove(0, sb.Length);
if (!function.StartsWith("gl"))
sb.Append("gl");
sb.Append(function);
FieldInfo f = DelegatesClass.GetField(sb.ToString(), BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
return f.GetValue(null) != null;
}
}
#endregion
#region public static bool SupportsFunction(string function, string extension)
/// <summary>
/// Checks if a given OpenGL function is supported by the current context
/// </summary>
/// <param name="function">The name of the OpenGL function (e.g. glShaderSource)</param>
/// <param name="extension">The name of the extension catagory (e.g. ARB, EXT, ATI, ...)</param>
/// <returns>True if the function is supported, false otherwise</returns>
public static bool SupportsFunction(string function, string extension)
{
lock (gl_lock)
{
if (function == null)
throw new ArgumentNullException("function");
if (extension == null)
throw new ArgumentNullException("extension");
sb.Remove(0, sb.Length);
if (!function.StartsWith("gl"))
sb.Append("gl");
sb.Append(function);
if (!function.EndsWith(extension))
sb.Append(extension);
FieldInfo f = delegatesClass.GetField(sb.ToString(), BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
return f.GetValue(null) != null;
}
}
#endregion
#region static bool SupportsFunction(MethodInfo function)
/// <summary>
/// Checks if a given OpenGL function is supported by the current context.
/// </summary>
/// <param name="function">The System.Reflection.MethodInfo for the OpenGL function.</param>
/// <returns>True if the function is supported, false otherwise.</returns>
static bool SupportsFunction(MethodInfo function)
{
if (function == null)
throw new ArgumentNullException("function");
AutoGeneratedAttribute[] attr = (AutoGeneratedAttribute[])
function.GetCustomAttributes(typeof(AutoGeneratedAttribute), false);
if (attr.Length == 0)
return false;
return SupportsFunction(attr[0].EntryPoint);
}
#endregion
#region private static void BuildExtensionList()
/// <summary>
/// Builds a cache of the supported extensions to speed up searches.
/// </summary>
private static void BuildExtensionList()
{
// Assumes there is an opengl context current.
AvailableExtensions.Clear();
string version_string = GL.GetString(StringName.Version);
if (String.IsNullOrEmpty(version_string))
{
throw new ApplicationException("Failed to build extension list. Is there an opengl context current?");
}
string version;
// Most drivers return the version in the 3 first characters of the version string,
// (e.g. on Ati X1950 with Catalyst 7.10 -> "2.0.6956 Release"). However, Mesa seems
// to do something strange: "1.4 (2.1 Mesa 7.0.1).".
// Update: this seems to occur with indirect rendering. E.g. Ati 8.2: 1.4 (2.1.7281 ...)
// We'll do some trickery to get the second number (2.1), but this may break on
// some implementations...
//if (version_string.ToLower().Contains("mesa"))
{
int index = version_string.IndexOf('(');
if (index != -1)
version = version_string.Substring(index + 1, 3);
else
version = version_string.TrimStart(' ');
}
//else
// version = version_string.TrimStart(' ');
if (version.StartsWith("1.1"))
{
AvailableExtensions.Add("glversion11", true);
}
else if (version.StartsWith("1.2"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
}
else if (version.StartsWith("1.3"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
}
else if (version.StartsWith("1.4"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
}
else if (version.StartsWith("1.5"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
AvailableExtensions.Add("glversion15", true);
}
else if (version.StartsWith("2.0"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
AvailableExtensions.Add("glversion15", true);
AvailableExtensions.Add("glversion20", true);
}
else if (version.StartsWith("2.1"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
AvailableExtensions.Add("glversion15", true);
AvailableExtensions.Add("glversion20", true);
AvailableExtensions.Add("glversion21", true);
}
else if (version.StartsWith("3.0"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
AvailableExtensions.Add("glversion15", true);
AvailableExtensions.Add("glversion20", true);
AvailableExtensions.Add("glversion21", true);
AvailableExtensions.Add("glversion30", true);
}
else if (version.StartsWith("3.1"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
AvailableExtensions.Add("glversion15", true);
AvailableExtensions.Add("glversion20", true);
AvailableExtensions.Add("glversion21", true);
AvailableExtensions.Add("glversion30", true);
AvailableExtensions.Add("glversion31", true);
}
else if (version.StartsWith("3.2"))
{
AvailableExtensions.Add("glversion11", true);
AvailableExtensions.Add("glversion12", true);
AvailableExtensions.Add("glversion13", true);
AvailableExtensions.Add("glversion14", true);
AvailableExtensions.Add("glversion15", true);
AvailableExtensions.Add("glversion20", true);
AvailableExtensions.Add("glversion21", true);
AvailableExtensions.Add("glversion30", true);
AvailableExtensions.Add("glversion31", true);
AvailableExtensions.Add("glversion32", true);
}
string extension_string = GL.GetString(StringName.Extensions);
if (String.IsNullOrEmpty(extension_string))
return; // no extensions are available
string[] extensions = extension_string.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string ext in extensions)
AvailableExtensions.Add(ext.Replace("_", String.Empty).ToLower(), true);
//rebuildExtensionList = false;
}
#endregion
#endif
#endregion
#region --- Protected Members ---
/// <summary>

View file

@ -35,7 +35,7 @@ namespace OpenTK.Platform
{
public override void LoadAll()
{
new OpenTK.Graphics.OpenGL.GL().LoadAll();
new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints();
}
}
}

View file

@ -26,8 +26,8 @@ namespace OpenTK.Platform.Dummy
#region --- Constructors ---
public DummyGLContext()
: this(new ContextHandle(new IntPtr(++handle_count)))
{
Handle = new ContextHandle(new IntPtr(++handle_count));
Mode = new GraphicsMode(new IntPtr(2), 32, 16, 0, 0, 0, 2, false);
}

View file

@ -35,9 +35,9 @@ namespace OpenTK.Platform
{
public override void LoadAll()
{
new OpenTK.Graphics.ES10.GL().LoadAll();
new OpenTK.Graphics.ES11.GL().LoadAll();
new OpenTK.Graphics.ES20.GL().LoadAll();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
}
}
}

View file

@ -99,6 +99,11 @@ namespace OpenTK.Platform
return default_implementation.CreateGLContext(mode, window, shareContext, directRendering, major, minor, flags);
}
public IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
return default_implementation.CreateGLContext(handle, window, shareContext, directRendering, major, minor, flags);
}
public GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
{
return default_implementation.CreateGetCurrentGraphicsContext();
@ -139,6 +144,11 @@ namespace OpenTK.Platform
throw new PlatformNotSupportedException(error_string);
}
public IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
throw new PlatformNotSupportedException(error_string);
}
public IGraphicsContext CreateESContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags)
{
throw new PlatformNotSupportedException(error_string);

View file

@ -41,6 +41,8 @@ namespace OpenTK.Platform
IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags);
IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags);
GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext();
IGraphicsMode CreateGraphicsMode();

View file

@ -47,6 +47,17 @@ namespace OpenTK.Platform.MacOS
CreateContext(mode, carbonWindow, shareContextRef, true);
}
public AglContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext)
{
if (handle == ContextHandle.Zero)
throw new ArgumentException("handle");
if (window == null)
throw new ArgumentNullException("window");
Handle = handle;
carbonWindow = (CarbonWindowInfo)window;
}
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
{

View file

@ -52,6 +52,11 @@ namespace OpenTK.Platform.MacOS
return new AglContext(mode, window, shareContext);
}
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
return new AglContext(handle, window, shareContext);
}
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
{
return (GraphicsContext.GetCurrentContextDelegate)delegate

View file

@ -53,6 +53,11 @@ namespace OpenTK.Platform.Windows
return new WinGLContext(mode, (WinWindowInfo)window, shareContext, major, minor, flags);
}
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
return new WinGLContext(handle, (WinWindowInfo)window, shareContext, major, minor, flags);
}
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
{
return (GraphicsContext.GetCurrentContextDelegate)delegate

View file

@ -141,6 +141,17 @@ namespace OpenTK.Platform.Windows
}
}
public WinGLContext(ContextHandle handle, WinWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
{
if (handle == ContextHandle.Zero)
throw new ArgumentException("handle");
if (window == null)
throw new ArgumentNullException("window");
Handle = handle;
}
#endregion
#region --- IGraphicsContext Members ---

View file

@ -60,6 +60,11 @@ namespace OpenTK.Platform.X11
return new X11GLContext(mode, window, shareContext, directRendering, major, minor, flags);
}
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
return new X11GLContext(handle, window, shareContext, directRendering, major, minor, flags);
}
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
{
return (GraphicsContext.GetCurrentContextDelegate)delegate

View file

@ -73,7 +73,7 @@ namespace OpenTK.Platform.X11
if (ctx != IntPtr.Zero)
{
new Glx().LoadAll();
new Glx().LoadEntryPoints();
Glx.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero);
//Glx.DestroyContext(Display, ctx);
glx_loaded = true;
@ -162,6 +162,19 @@ namespace OpenTK.Platform.X11
Debug.Print("Warning: Context is not direct.");
}
public X11GLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shared, bool direct,
int major, int minor, GraphicsContextFlags flags)
{
if (handle == ContextHandle.Zero)
throw new ArgumentException("handle");
if (window == null)
throw new ArgumentNullException("window");
Handle = handle;
currentWindow = (X11WindowInfo)window;
Display = currentWindow.Display;
}
#endregion
#region --- Private Methods ---
@ -318,7 +331,7 @@ namespace OpenTK.Platform.X11
public override void LoadAll()
{
new Glx().LoadAll();
new Glx().LoadEntryPoints();
vsync_supported = this.GetAddress("glXSwapIntervalSGI") != IntPtr.Zero;
Debug.Print("Context supports vsync: {0}.", vsync_supported);