Added BindingsBase class that provides a common base for all generated bindings.

Made the OpenGL and OpenGL|ES bindings non static.
Made the OpenGL and OpenGL|ES bindings inherit from BindingsBase.
This commit is contained in:
the_fiddler 2009-08-17 10:20:42 +00:00
parent 235a12d549
commit 52263700fd
5 changed files with 230 additions and 245 deletions

View file

@ -0,0 +1,208 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2009 the Open Toolkit library.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace OpenTK.Graphics
{
/// <summary>
/// Provides a common foundation for all flat API classes.
/// </summary>
public abstract class BindingsBase
{
#region Fields
/// <summary>
/// A reflection handle to the nested type that contains the function delegates.
/// </summary>
readonly protected Type DelegatesClass;
/// <summary>
/// A refection handle to the nested type that contains core functions (i.e. not extensions).
/// </summary>
readonly protected Type CoreClass;
/// <summary>
/// A mapping of core function names to MethodInfo handles.
/// </summary>
readonly protected SortedList<string, MethodInfo> CoreFunctionMap = new SortedList<string, MethodInfo>();
bool rebuildExtensionList = true;
#endregion
#region Constructors
/// <summary>
/// Constructs a new BindingsBase instance.
/// </summary>
public BindingsBase()
{
DelegatesClass = this.GetType().GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
CoreClass = this.GetType().GetNestedType("Core", BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo[] methods = CoreClass.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
CoreFunctionMap = new SortedList<string, MethodInfo>(methods.Length);
foreach (MethodInfo m in methods)
{
CoreFunctionMap.Add(m.Name, m);
}
}
#endregion
#region Protected Members
/// <summary>
/// Gets or sets a <see cref="System.Boolean"/> that indicates whether the list of supported extensions may have changed.
/// </summary>
protected bool RebuildExtensionList
{
get { return rebuildExtensionList; }
set { rebuildExtensionList = value; }
}
#endregion
#region Internal Members
#region LoadAll
internal void LoadAll()
{
// 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
// than with reflection, but the first time is more significant.
int supported = 0;
FieldInfo[] delegates = DelegatesClass.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (delegates == null)
throw new InvalidOperationException("The specified type does not have any loadable extensions.");
Debug.Write("Load extensions for " + this.GetType().FullName + "... ");
System.Diagnostics.Stopwatch time = new System.Diagnostics.Stopwatch();
time.Reset();
time.Start();
foreach (FieldInfo f in delegates)
{
Delegate d = LoadDelegate(f.Name, f.FieldType);
if (d != null)
++supported;
f.SetValue(null, d);
}
rebuildExtensionList = true;
time.Stop();
Debug.Print("{0} extensions loaded in {1} ms.", supported, time.ElapsedMilliseconds);
time.Reset();
}
#endregion
#region Load
/// <summary>
/// Loads all extension and core functions.
/// </summary>
internal bool Load(string function)
{
FieldInfo f = DelegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
Delegate old = f.GetValue(null) as Delegate;
Delegate @new = LoadDelegate(f.Name, f.FieldType);
if (old.Target != @new.Target)
{
f.SetValue(null, @new);
}
return @new != null;
}
#endregion
#endregion
#region Private Members
#region LoadDelegate
/// <summary>
/// Tries to load the specified core or extension function.
/// </summary>
/// <param name="function">The name of the function (i.e. glShaderSource)</param>
/// <returns>True if the function was found and reloaded, false otherwise.</returns>
/// <remarks>
/// <para>
/// Use this function if you require greater granularity when loading entry points.
/// </para>
/// </remarks>
Delegate LoadDelegate(string name, Type signature)
{
MethodInfo m;
return
GetExtensionDelegate(name, signature) ??
(CoreFunctionMap.TryGetValue((name.Substring(2)), out m) ?
Delegate.CreateDelegate(signature, m) : null);
}
#endregion
#region GetExtensionDelegate
// Creates a System.Delegate that can be used to call a dynamically exported OpenGL function.
internal static Delegate GetExtensionDelegate(string name, Type signature)
{
IntPtr address = (GraphicsContext.CurrentContext as IGraphicsContextInternal).GetAddress(name);
if (address == IntPtr.Zero ||
address == new IntPtr(1) || // Workaround for buggy nvidia drivers which return
address == new IntPtr(2)) // 1 or 2 instead of IntPtr.Zero for some extensions.
{
return null;
}
else
{
return Marshal.GetDelegateForFunctionPointer(address, signature);
}
}
#endregion
#endregion
}
}

View file

@ -7,7 +7,7 @@ namespace OpenTK.Graphics.ES10
/// <summary>
/// Provides access to OpenGL ES 1.0 methods.
/// </summary>
public static partial class GL
public sealed partial class GL : BindingsBase
{
const string Library = "libGLES.dll";
}

View file

@ -9,118 +9,8 @@ namespace OpenTK.Graphics.ES11
/// <summary>
/// Provides access to OpenGL ES 1.1 methods.
/// </summary>
public partial class GL
public sealed partial class GL : BindingsBase
{
#region Fields
const string Library = "libGLES.dll";
readonly static Type delegatesClass = typeof(GL).GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
readonly static Type importsClass = typeof(GL).GetNestedType("Core", BindingFlags.Static | BindingFlags.NonPublic);
readonly static SortedList<string, MethodInfo> FunctionMap = new SortedList<string, MethodInfo>();
#endregion
#region Constructors
static GL()
{
MethodInfo[] methods = importsClass.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
FunctionMap = new SortedList<string, MethodInfo>(methods.Length);
foreach (MethodInfo m in methods)
{
FunctionMap.Add(m.Name, m);
}
}
internal GL()
{
//if (GraphicsContext.CurrentContext == null)
// throw new GraphicsContextMissingException();
//FieldInfo[] delegates = this.GetType()
// .GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic)
// .GetFields(BindingFlags.Static | BindingFlags.NonPublic);
//if (delegates == null)
// throw new Exception("Internal OpenTK error: ES11 bindings not generated correctly. Please report to http://www.opentk.com/issues");
//for (int i = 0; i < delegates.Length; i++)
//{
//}
}
#endregion
#region Private Members
#region LoadAll
internal static void LoadAll()
{
if (GraphicsContext.CurrentContext == null)
throw new GraphicsContextMissingException();
OpenTK.Platform.Utilities.LoadExtensions(typeof(GL));
}
#endregion
#region Load
static bool Load(string function)
{
FieldInfo f = delegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
Delegate old = f.GetValue(null) as Delegate;
Delegate @new = LoadDelegate(f.Name, f.FieldType);
if (old.Target != @new.Target)
{
f.SetValue(null, @new);
}
return @new != null;
}
#endregion
#region LoadDelegate
static Delegate LoadDelegate(string name, Type signature)
{
MethodInfo m;
return
GetExtensionDelegate(name, signature) ??
(FunctionMap.TryGetValue((name.Substring(2)), out m) ?
Delegate.CreateDelegate(signature, m) : null);
}
#endregion
#region GetExtensionDelegate
// Creates a System.Delegate that can be used to call a dynamically exported OpenGL function.
internal static Delegate GetExtensionDelegate(string name, Type signature)
{
IntPtr address = (GraphicsContext.CurrentContext as IGraphicsContextInternal).GetAddress(name);
if (address == IntPtr.Zero ||
address == new IntPtr(1) || // Workaround for buggy nvidia drivers which return
address == new IntPtr(2)) // 1 or 2 instead of IntPtr.Zero for some extensions.
{
return null;
}
else
{
return Marshal.GetDelegateForFunctionPointer(address, signature);
}
}
#endregion
#endregion
}
}

View file

@ -7,7 +7,7 @@ namespace OpenTK.Graphics.ES20
/// <summary>
/// Provides access to OpenGL ES 2.0 methods.
/// </summary>
public static partial class GL
public sealed partial class GL : BindingsBase
{
const string Library = "libGLESv2.dll";
}

View file

@ -50,7 +50,7 @@ namespace OpenTK.Graphics.OpenGL
/// <seealso cref="GL.GetDelegate(string)"/>
/// <seealso cref="GL.LoadAll"/>
/// <seealso cref="GL.Load"/>
public static partial class GL
public sealed partial class GL : BindingsBase
{
#region --- Fields ---
@ -60,13 +60,6 @@ namespace OpenTK.Graphics.OpenGL
static object gl_lock = new object();
private static SortedList<string, bool> AvailableExtensions = new SortedList<string, bool>();
private static bool rebuildExtensionList;
private static Type glClass;
private static Type delegatesClass;
private static Type importsClass;
readonly static SortedList<string, MethodInfo> FunctionMap = new SortedList<string, MethodInfo>();
#endregion
@ -74,22 +67,12 @@ namespace OpenTK.Graphics.OpenGL
static GL()
{
glClass = typeof(GL);
delegatesClass = glClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
importsClass = glClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo[] methods = importsClass.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
FunctionMap = new SortedList<string, MethodInfo>(methods.Length);
foreach (MethodInfo m in methods)
{
FunctionMap.Add(m.Name, m);
}
}
#endregion
#region --- Public Members ---
#if false
#region public static bool SupportsExtension(string name)
/// <summary>
@ -100,7 +83,7 @@ namespace OpenTK.Graphics.OpenGL
/// <returns>True if the specified extension is available, false otherwise.</returns>
public static bool SupportsExtension(string name)
{
if (rebuildExtensionList)
if (RebuildExtensionList)
BuildExtensionList();
lock (gl_lock)
@ -140,115 +123,6 @@ namespace OpenTK.Graphics.OpenGL
#endregion
#region public static Delegate GetDelegate(string name, Type signature)
/// <summary>
/// Returns a System.Delegate wrapping an OpenGL function.
/// </summary>
/// <param name="name">The name of the OpenGL function (eg. "glNewList")</param>
/// <param name="signature">The signature of the OpenGL function.</param>
/// <returns>
/// A System.Delegate that can be used to call this OpenGL function, or null if the specified
/// function name did not correspond to an OpenGL function.
/// </returns>
[Obsolete("Use GetDelegate(string name) instead.")]
public static Delegate GetDelegate(string name, Type signature)
{
return LoadDelegate(name, signature);
}
#endregion
#region public static void LoadAll()
/// <summary>
/// Loads all OpenGL functions (core and extensions).
/// </summary>
/// <remarks>
/// <para>
/// This function will be automatically called the first time you use any opengl function. There is
/// </para>
/// <para>
/// Call this function manually whenever you need to update OpenGL entry points.
/// This need may arise if you change the pixelformat/visual, or in case you cannot
/// (or do not want) to use the automatic initialization of the GL class.
/// </para>
/// </remarks>
public static void LoadAll()
{
if (GraphicsContext.CurrentContext == null)
throw new GraphicsContextMissingException();
OpenTK.Platform.Utilities.LoadExtensions(glClass);
}
#endregion
#region public static bool Load(string function)
/// <summary>
/// Tries to reload the given OpenGL function (core or extension).
/// </summary>
/// <param name="function">The name of the OpenGL function (i.e. glShaderSource)</param>
/// <returns>True if the function was found and reloaded, false otherwise.</returns>
/// <remarks>
/// <para>
/// Use this function if you require greater granularity when loading OpenGL entry points.
/// </para>
/// <para>
/// While the automatic initialisation will load all OpenGL entry points, in some cases
/// the initialisation can take place before an OpenGL Context has been established.
/// In this case, use this function to load the entry points for the OpenGL functions
/// you will need, or use ReloadFunctions() to load all available entry points.
/// </para>
/// <para>
/// This function returns true if the given OpenGL function is supported, false otherwise.
/// </para>
/// <para>
/// To query for supported extensions use the IsExtensionSupported() function instead.
/// </para>
/// </remarks>
public static bool Load(string function)
{
FieldInfo f = delegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
Delegate old = f.GetValue(null) as Delegate;
Delegate @new = LoadDelegate(f.Name, f.FieldType);
if (old.Target != @new.Target)
{
f.SetValue(null, @new);
rebuildExtensionList = true;
}
return @new != null;
}
#endregion
#region static Delegate LoadDelegate(string name, Type signature)
/// <private />
/// <summary>
/// Loads an OpenGL function into a type-safe System.Delegate.
/// </summary>
/// <param name="name">The name of the OpenGL function (eg. "glNewList")</param>
/// <param name="signature">The signature of the OpenGL function.</param>
/// <returns>
/// A System.Delegate that can be used to call this OpenGL function, or null if the specified
/// function name did not correspond to an OpenGL function.
/// </returns>
static Delegate LoadDelegate(string name, Type signature)
{
MethodInfo m;
return
GetExtensionDelegate(name, signature) ??
(FunctionMap.TryGetValue((name.Substring(2)), out m) ?
Delegate.CreateDelegate(signature, m) : null);
}
#endregion
#region public static bool SupportsFunction(string function)
/// <summary>
@ -267,7 +141,7 @@ namespace OpenTK.Graphics.OpenGL
if (!function.StartsWith("gl"))
sb.Append("gl");
sb.Append(function);
FieldInfo f = delegatesClass.GetField(sb.ToString(), BindingFlags.Static | BindingFlags.NonPublic);
FieldInfo f = DelegatesClass.GetField(sb.ToString(), BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
@ -332,7 +206,7 @@ namespace OpenTK.Graphics.OpenGL
}
#endregion
#endif
#region private static void BuildExtensionList()
/// <summary>
@ -439,6 +313,19 @@ namespace OpenTK.Graphics.OpenGL
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))
@ -448,7 +335,7 @@ namespace OpenTK.Graphics.OpenGL
foreach (string ext in extensions)
AvailableExtensions.Add(ext.Replace("_", String.Empty).ToLower(), true);
rebuildExtensionList = false;
//rebuildExtensionList = false;
}
#endregion