diff --git a/Source/OpenTK/Graphics/BindingsBase.cs b/Source/OpenTK/Graphics/BindingsBase.cs new file mode 100644 index 00000000..48105445 --- /dev/null +++ b/Source/OpenTK/Graphics/BindingsBase.cs @@ -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 +{ + /// + /// Provides a common foundation for all flat API classes. + /// + public abstract class BindingsBase + { + #region Fields + + /// + /// A reflection handle to the nested type that contains the function delegates. + /// + readonly protected Type DelegatesClass; + + /// + /// A refection handle to the nested type that contains core functions (i.e. not extensions). + /// + readonly protected Type CoreClass; + + /// + /// A mapping of core function names to MethodInfo handles. + /// + readonly protected SortedList CoreFunctionMap = new SortedList(); + + bool rebuildExtensionList = true; + + #endregion + + #region Constructors + + /// + /// Constructs a new BindingsBase instance. + /// + 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(methods.Length); + foreach (MethodInfo m in methods) + { + CoreFunctionMap.Add(m.Name, m); + } + } + + #endregion + + #region Protected Members + + /// + /// Gets or sets a that indicates whether the list of supported extensions may have changed. + /// + 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 + + /// + /// Loads all extension and core functions. + /// + 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 + + /// + /// Tries to load the specified core or extension function. + /// + /// The name of the function (i.e. glShaderSource) + /// True if the function was found and reloaded, false otherwise. + /// + /// + /// Use this function if you require greater granularity when loading entry points. + /// + /// + 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 + } +} diff --git a/Source/OpenTK/Graphics/ES10/Helper.cs b/Source/OpenTK/Graphics/ES10/Helper.cs index eee60bb9..dee53b56 100644 --- a/Source/OpenTK/Graphics/ES10/Helper.cs +++ b/Source/OpenTK/Graphics/ES10/Helper.cs @@ -7,7 +7,7 @@ namespace OpenTK.Graphics.ES10 /// /// Provides access to OpenGL ES 1.0 methods. /// - public static partial class GL + public sealed partial class GL : BindingsBase { const string Library = "libGLES.dll"; } diff --git a/Source/OpenTK/Graphics/ES11/Helper.cs b/Source/OpenTK/Graphics/ES11/Helper.cs index 1ade9ba1..1b0fab28 100644 --- a/Source/OpenTK/Graphics/ES11/Helper.cs +++ b/Source/OpenTK/Graphics/ES11/Helper.cs @@ -9,118 +9,8 @@ namespace OpenTK.Graphics.ES11 /// /// Provides access to OpenGL ES 1.1 methods. /// - 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 FunctionMap = new SortedList(); - - #endregion - - #region Constructors - - static GL() - { - MethodInfo[] methods = importsClass.GetMethods(BindingFlags.Static | BindingFlags.NonPublic); - FunctionMap = new SortedList(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 } } diff --git a/Source/OpenTK/Graphics/ES20/Helper.cs b/Source/OpenTK/Graphics/ES20/Helper.cs index 09cdc1b5..ccd1d4c2 100644 --- a/Source/OpenTK/Graphics/ES20/Helper.cs +++ b/Source/OpenTK/Graphics/ES20/Helper.cs @@ -7,7 +7,7 @@ namespace OpenTK.Graphics.ES20 /// /// Provides access to OpenGL ES 2.0 methods. /// - public static partial class GL + public sealed partial class GL : BindingsBase { const string Library = "libGLESv2.dll"; } diff --git a/Source/OpenTK/Graphics/OpenGL/GLHelper.cs b/Source/OpenTK/Graphics/OpenGL/GLHelper.cs index ef0627c3..4a68cec9 100644 --- a/Source/OpenTK/Graphics/OpenGL/GLHelper.cs +++ b/Source/OpenTK/Graphics/OpenGL/GLHelper.cs @@ -50,7 +50,7 @@ namespace OpenTK.Graphics.OpenGL /// /// /// - 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 AvailableExtensions = new SortedList(); - private static bool rebuildExtensionList; - - private static Type glClass; - private static Type delegatesClass; - private static Type importsClass; - - readonly static SortedList FunctionMap = new SortedList(); #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(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) /// @@ -100,7 +83,7 @@ namespace OpenTK.Graphics.OpenGL /// True if the specified extension is available, false otherwise. 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) - - /// - /// Returns a System.Delegate wrapping an OpenGL function. - /// - /// The name of the OpenGL function (eg. "glNewList") - /// The signature of the OpenGL function. - /// - /// 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. - /// - [Obsolete("Use GetDelegate(string name) instead.")] - public static Delegate GetDelegate(string name, Type signature) - { - return LoadDelegate(name, signature); - } - - #endregion - - #region public static void LoadAll() - - /// - /// Loads all OpenGL functions (core and extensions). - /// - /// - /// - /// This function will be automatically called the first time you use any opengl function. There is - /// - /// - /// 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. - /// - /// - public static void LoadAll() - { - if (GraphicsContext.CurrentContext == null) - throw new GraphicsContextMissingException(); - - OpenTK.Platform.Utilities.LoadExtensions(glClass); - } - - #endregion - - #region public static bool Load(string function) - - /// - /// Tries to reload the given OpenGL function (core or extension). - /// - /// The name of the OpenGL function (i.e. glShaderSource) - /// True if the function was found and reloaded, false otherwise. - /// - /// - /// Use this function if you require greater granularity when loading OpenGL entry points. - /// - /// - /// 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. - /// - /// - /// This function returns true if the given OpenGL function is supported, false otherwise. - /// - /// - /// To query for supported extensions use the IsExtensionSupported() function instead. - /// - /// - 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) - - /// - /// - /// Loads an OpenGL function into a type-safe System.Delegate. - /// - /// The name of the OpenGL function (eg. "glNewList") - /// The signature of the OpenGL function. - /// - /// 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. - /// - 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) /// @@ -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() /// @@ -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