From 5598019f0155b6a726876e0a0c8884a436a6aeb2 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Tue, 22 Jan 2008 23:58:50 +0000 Subject: [PATCH] Refactored extension loading to remove duplicate code. The logic is now contained in OpenTK/Platform/Utilities.cs --- Source/OpenTK/OpenGL/GLHelper.cs | 42 +------ Source/OpenTK/OpenGL/GluHelper.cs | 38 ++---- Source/OpenTK/Platform/IGLContext.cs | 2 +- Source/OpenTK/Platform/Utilities.cs | 125 ++++++++++++++++++++ Source/OpenTK/Platform/Windows/WglHelper.cs | 44 ++----- 5 files changed, 152 insertions(+), 99 deletions(-) diff --git a/Source/OpenTK/OpenGL/GLHelper.cs b/Source/OpenTK/OpenGL/GLHelper.cs index 19687f9f..c3972895 100644 --- a/Source/OpenTK/OpenGL/GLHelper.cs +++ b/Source/OpenTK/OpenGL/GLHelper.cs @@ -105,7 +105,7 @@ namespace OpenTK.OpenGL #endregion - #region --- Methods --- + #region --- Public Methods --- #region public static bool SupportsExtension(string name) @@ -193,43 +193,11 @@ namespace OpenTK.OpenGL /// public static 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. + //TODO: Route GameWindow context creation through GLContext. + //if (GLContext.CurrentContext == null) + // throw new InvalidOperationException("You must create an OpenGL context before using the GL class."); - int supported = 0; - if (delegates == null) - { - delegates = delegatesClass.GetFields(BindingFlags.Static | BindingFlags.NonPublic); - } - - Trace.Write("GL.LoadAll(): "); - - 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); - } - - time.Stop(); - Trace.WriteLine(String.Format("{0} OpenGL extensions loaded in {1} milliseconds.", supported, time.ElapsedMilliseconds)); - time.Reset(); - - rebuildExtensionList = true; - } - - static void set(object d, Delegate value) - { - d = value; + OpenTK.Platform.Utilities.LoadExtensions(glClass); } #endregion diff --git a/Source/OpenTK/OpenGL/GluHelper.cs b/Source/OpenTK/OpenGL/GluHelper.cs index f1f7d0d6..2fa33374 100644 --- a/Source/OpenTK/OpenGL/GluHelper.cs +++ b/Source/OpenTK/OpenGL/GluHelper.cs @@ -25,20 +25,20 @@ namespace OpenTK.OpenGL private static Dictionary AvailableExtensions = new Dictionary(); private static bool rebuildExtensionList = true; - private static Assembly assembly; - private static Type glClass; - private static Type delegatesClass; - private static Type importsClass; + //private static Assembly assembly; + //private static Type glClass; + //private static Type delegatesClass; + private static Type importsClass = typeof(Imports); static Glu() { - assembly = Assembly.GetExecutingAssembly();//Assembly.Load("OpenTK.OpenGL"); - glClass = assembly.GetType("OpenTK.OpenGL.Glu"); - delegatesClass = glClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic); - importsClass = glClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic); + //assembly = Assembly.GetExecutingAssembly();//Assembly.Load("OpenTK.OpenGL"); + //glClass = assembly.GetType("OpenTK.OpenGL.Glu"); + //delegatesClass = glClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic); + //importsClass = glClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic); } - #region private static Delegate GetDelegate(string name, Type signature) + #region private static Delegate LoadDelegate(string name, Type signature) /// /// Creates a System.Delegate that can be used to call a GLU function, core or extension. @@ -49,7 +49,7 @@ namespace OpenTK.OpenGL /// A System.Delegate that can be used to call this GLU function, or null if the specified /// function name did not correspond to an GLU function. /// - private static Delegate GetDelegate(string name, Type signature) + private static Delegate LoadDelegate(string name, Type signature) { MethodInfo m = importsClass.GetMethod(name.Substring(3), BindingFlags.Static | BindingFlags.NonPublic); return @@ -72,14 +72,7 @@ namespace OpenTK.OpenGL /// public static void LoadAll() { - FieldInfo[] v = delegatesClass.GetFields(BindingFlags.Static | BindingFlags.NonPublic); - foreach (FieldInfo f in v) - { - f.SetValue(null, GetDelegate(f.Name, f.FieldType)); - } - - AvailableExtensions.Clear(); - rebuildExtensionList = true; + OpenTK.Platform.Utilities.LoadExtensions(typeof(Glu)); } #endregion @@ -107,14 +100,7 @@ namespace OpenTK.OpenGL /// public static bool Load(string function) { - FieldInfo f = delegatesClass.GetField(function); - if (f == null) - return false; - - f.SetValue(null, GetDelegate(f.Name, f.FieldType)); - - rebuildExtensionList = true; - return f.GetValue(null) != null; + return OpenTK.Platform.Utilities.TryLoadExtension(typeof(Glu), function); } #endregion diff --git a/Source/OpenTK/Platform/IGLContext.cs b/Source/OpenTK/Platform/IGLContext.cs index ddebc655..59259f22 100644 --- a/Source/OpenTK/Platform/IGLContext.cs +++ b/Source/OpenTK/Platform/IGLContext.cs @@ -117,7 +117,7 @@ namespace OpenTK.Platform /// A pointer to the specified function or IntPtr.Zero if the function isn't /// available in the current opengl context. /// - /// + // /// IntPtr GetAddress(string function); } } diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index 75fb79ed..5137a039 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -11,6 +11,8 @@ using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; +using System.Reflection; +using System.Diagnostics; #endregion @@ -21,6 +23,8 @@ namespace OpenTK.Platform /// public static class Utilities { + #region internal static bool ThrowOnX11Error + static bool throw_on_error; internal static bool ThrowOnX11Error { @@ -46,6 +50,127 @@ namespace OpenTK.Platform } } + #endregion + + #region internal static void LoadExtensions(Type type) + + delegate Delegate LoadDelegateFunction(string name, Type signature); + + /// + /// Loads all extensions for the specified class. This function is intended + /// for OpenGL, Wgl, Glx, OpenAL etc. + /// The class to load extensions for. + /// + /// The Type must contain a nested class called "Delegates". + /// + /// The Type must also implement a static function called LoadDelegate with the + /// following signature: + /// static Delegate LoadDelegate(string name, Type signature) + /// + /// This function allocates memory. + /// + internal static void LoadExtensions(Type type) + { + // 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; + Type extensions_class = type.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic); + if (extensions_class == null) + throw new InvalidOperationException("The specified type does not have any loadable extensions."); + + FieldInfo[] delegates = extensions_class.GetFields(BindingFlags.Static | BindingFlags.NonPublic); + if (delegates == null) + throw new InvalidOperationException("The specified type does not have any loadable extensions."); + + MethodInfo load_delegate_method_info = type.GetMethod("LoadDelegate", BindingFlags.Static | BindingFlags.NonPublic); + if (load_delegate_method_info == null) + throw new InvalidOperationException(type.ToString() + " does not contain a static LoadDelegate method."); + LoadDelegateFunction LoadDelegate = (LoadDelegateFunction)Delegate.CreateDelegate( + typeof(LoadDelegateFunction), load_delegate_method_info); + + Debug.Write("Load extensions for " + type.ToString() + "... "); + + 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); + } + + FieldInfo rebuildExtensionList = type.GetField("rebuildExtensionList", BindingFlags.Static | BindingFlags.NonPublic); + if (rebuildExtensionList != null) + rebuildExtensionList.SetValue(null, true); + + time.Stop(); + Debug.Print("{0} extensions loaded in {1} ms.", supported, time.ElapsedMilliseconds); + time.Reset(); + } + + #endregion + + #region internal static void LoadExtension() + + /// + /// Loads the specified extension for the specified class. This function is intended + /// for OpenGL, Wgl, Glx, OpenAL etc. + /// The class to load extensions for. + /// The extension to load. + /// + /// The Type must contain a nested class called "Delegates". + /// + /// The Type must also implement a static function called LoadDelegate with the + /// following signature: + /// static Delegate LoadDelegate(string name, Type signature) + /// + /// This function allocates memory. + /// + internal static bool TryLoadExtension(Type type, string extension) + { + Type extensions_class = type.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic); + if (extensions_class == null) + { + Debug.Print(type.ToString(), " does not contain extensions."); + return false; + } + + LoadDelegateFunction LoadDelegate = (LoadDelegateFunction)Delegate.CreateDelegate(typeof(LoadDelegateFunction), + type.GetMethod("LoadDelegate", BindingFlags.Static | BindingFlags.NonPublic)); + if (LoadDelegate == null) + { + Debug.Print(type.ToString(), " does not contain a static LoadDelegate method."); + return false; + } + + FieldInfo f = type.GetField(extension, BindingFlags.Static | BindingFlags.NonPublic); + if (f == null) + { + Debug.Print("Extension \"", extension, "\" not found in ", type.ToString()); + 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); + FieldInfo rebuildExtensionList = type.GetField("rebuildExtensionList", BindingFlags.Static | BindingFlags.NonPublic); + if (rebuildExtensionList != null) + rebuildExtensionList.SetValue(null, true); + } + return @new != null; + } + + #endregion + + #region public bool IsIdle interface IIsIdle { bool IsIdle { get; } } diff --git a/Source/OpenTK/Platform/Windows/WglHelper.cs b/Source/OpenTK/Platform/Windows/WglHelper.cs index bf55aba1..8dede925 100644 --- a/Source/OpenTK/Platform/Windows/WglHelper.cs +++ b/Source/OpenTK/Platform/Windows/WglHelper.cs @@ -41,12 +41,11 @@ namespace OpenTK.Platform.Windows private static Type delegatesClass; private static Type importsClass; - private static bool reload_ext_extension_strings = true; - private static bool reload_arb_extension_strings = true; + private static bool rebuildExtensionList = true; #endregion - #region public static Delegate GetDelegate(string name, Type signature) + #region static Delegate LoadDelegate(string name, Type signature) /// /// Creates a System.Delegate that can be used to call an OpenGL function, core or extension. @@ -57,21 +56,17 @@ namespace OpenTK.Platform.Windows /// 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. /// - public static Delegate GetDelegate(string name, Type signature) + static Delegate LoadDelegate(string name, Type signature) { Delegate d; string realName = name.StartsWith("wgl") ? name.Substring(3) : name; if (importsClass.GetMethod(realName, BindingFlags.NonPublic | BindingFlags.Static) != null) - { d = GetExtensionDelegate(name, signature) ?? Delegate.CreateDelegate(signature, typeof(Imports), realName); - } else - { d = GetExtensionDelegate(name, signature); - } return d; } @@ -114,13 +109,7 @@ namespace OpenTK.Platform.Windows /// public static void LoadAll() { - FieldInfo[] v = delegatesClass.GetFields(BindingFlags.Static | BindingFlags.NonPublic); - foreach (FieldInfo f in v) - { - f.SetValue(null, GetDelegate(f.Name, f.FieldType)); - } - reload_ext_extension_strings = true; - reload_arb_extension_strings = true; + OpenTK.Platform.Utilities.LoadExtensions(typeof(Wgl)); } #endregion @@ -134,22 +123,7 @@ namespace OpenTK.Platform.Windows /// 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 = GetDelegate(f.Name, f.FieldType); - - if (old.Target != @new.Target) - { - f.SetValue(null, @new); - if (function.EndsWith("EXT")) - reload_ext_extension_strings = true; - else if (function.EndsWith("ARB")) - reload_arb_extension_strings = true; - } - return @new != null; + return OpenTK.Platform.Utilities.TryLoadExtension(typeof(Wgl), function); } #endregion @@ -200,11 +174,11 @@ namespace OpenTK.Platform.Windows { if (Wgl.Delegates.wglGetExtensionsStringARB != null) { - if (extensions == null || reload_arb_extension_strings) + if (extensions == null || rebuildExtensionList) { extensions = Wgl.Arb.GetExtensionsString(deviceContext).Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); Array.Sort(extensions); - reload_arb_extension_strings = false; + rebuildExtensionList = false; } return Array.BinarySearch(extensions, ext) != -1; @@ -227,11 +201,11 @@ namespace OpenTK.Platform.Windows { if (Wgl.Delegates.wglGetExtensionsStringEXT != null) { - if (extensions == null || reload_ext_extension_strings) + if (extensions == null || rebuildExtensionList) { extensions = Wgl.Ext.GetExtensionsString().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); Array.Sort(extensions); - reload_ext_extension_strings = false; + rebuildExtensionList = false; } return Array.BinarySearch(extensions, ext) != -1;