#region --- License --- /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos * See license.txt for license info * * Date: 12/8/2007 * Time: 6:43 �� */ #endregion using System; using System.Runtime.InteropServices; using System.Reflection; namespace OpenTK.Platform.Windows { internal partial class Wgl { #region --- Constructors --- static Wgl() { assembly = Assembly.GetExecutingAssembly(); wglClass = assembly.GetType("OpenTK.Platform.Windows.Wgl"); delegatesClass = wglClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic); importsClass = wglClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic); // Ensure core entry points are ready prior to accessing any method. // Resolves bug [#993]: "Possible bug in GraphicsContext.CreateDummyContext()" LoadAll(); } #endregion #region --- Fields --- internal const string Library = "OPENGL32.DLL"; private static Assembly assembly; private static Type wglClass; private static Type delegatesClass; private static Type importsClass; private static bool rebuildExtensionList = true; #endregion #region static Delegate LoadDelegate(string name, Type signature) /// /// Creates a System.Delegate that can be used to call an OpenGL function, core or extension. /// /// The name of the Wgl function (eg. "wglNewList") /// 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) { 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; } #endregion #region private static Delegate GetExtensionDelegate(string name, Type signature) /// /// Creates a System.Delegate that can be used to call a dynamically exported 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 function is not available in the current OpenGL context. /// private static Delegate GetExtensionDelegate(string name, Type signature) { IntPtr address = Imports.GetProcAddress(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 #region public static void LoadAll() /// /// Loads all Wgl entry points, core and extensions. /// public static void LoadAll() { OpenTK.Platform.Utilities.LoadExtensions(typeof(Wgl)); } #endregion #region public static bool Load(string function) /// /// Loads the given Wgl entry point. /// /// The name of the function to load. /// public static bool Load(string function) { return OpenTK.Platform.Utilities.TryLoadExtension(typeof(Wgl), function); } #endregion #region public static partial class Arb /// Contains ARB extensions for WGL. public static partial class Arb { /// /// Checks if a Wgl extension is supported by the given context. /// /// The device context. /// The extension to check. /// True if the extension is supported by the given context, false otherwise public static bool SupportsExtension(WinGLContext context, string ext) { // We cache this locally, as another thread might create a context which doesn't support this method. // The design is far from ideal, but there's no good solution to this issue as long as we are using // static WGL/GL classes. Fortunately, this issue is extremely unlikely to arise in practice, as you'd // have to create one accelerated and one non-accelerated context in the same application, with the // non-accelerated context coming second. Wgl.Delegates.GetExtensionsStringARB get = Wgl.Delegates.wglGetExtensionsStringARB; if (get != null) { string[] extensions = null; unsafe { extensions = new string((sbyte*)get(context.DeviceContext)) .Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); } if (extensions == null || extensions.Length == 0) return false; foreach (string s in extensions) if (s == ext) return true; } return false; } } #endregion #region public static partial class Ext /// Contains EXT extensions for WGL. public static partial class Ext { private static string[] extensions; /// /// Checks if a Wgl extension is supported by the given context. /// /// The extension to check. /// True if the extension is supported by the given context, false otherwise public static bool SupportsExtension(string ext) { if (Wgl.Delegates.wglGetExtensionsStringEXT != null) { if (extensions == null || rebuildExtensionList) { extensions = Wgl.Ext.GetExtensionsString().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); Array.Sort(extensions); rebuildExtensionList = false; } return Array.BinarySearch(extensions, ext) != -1; } return false; } } #endregion } }