#region --- License --- /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos * See license.txt for license info */ #endregion #region --- Using Directives --- using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Reflection; using System.Diagnostics; using OpenTK.Graphics; #endregion namespace OpenTK.Platform { /// /// Provides cross-platform utilities to help interact with the underlying platform. /// public static class Utilities { #region internal static bool ThrowOnX11Error static bool throw_on_error; internal static bool ThrowOnX11Error { get { return throw_on_error; } set { if (value && !throw_on_error) { Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms") .GetField("ErrorExceptions", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) .SetValue(null, true); throw_on_error = true; } else if (!value && throw_on_error) { Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms") .GetField("ErrorExceptions", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) .SetValue(null, false); throw_on_error = false; } } } #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 | BindingFlags.Public); 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 | BindingFlags.Public); 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 | BindingFlags.Public); 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 | BindingFlags.Public); 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 bool TryLoadExtension(Type type, string extension) /// /// 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 | BindingFlags.Public); 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 | BindingFlags.Public)); if (LoadDelegate == null) { Debug.Print(type.ToString(), " does not contain a static LoadDelegate method."); return false; } FieldInfo f = extensions_class.GetField(extension, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); 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 != null ? old.Target : null) != (@new != null ? @new.Target : null)) { f.SetValue(null, @new); FieldInfo rebuildExtensionList = type.GetField("rebuildExtensionList", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); if (rebuildExtensionList != null) rebuildExtensionList.SetValue(null, true); } return @new != null; } #endregion #region CreateGetAddress internal static GraphicsContext.GetAddressDelegate CreateGetAddress() { GraphicsContext.GetAddressDelegate loader = null; if (Configuration.RunningOnWindows) { loader = Platform.Windows.Wgl.GetProcAddress; } else if (Configuration.RunningOnX11) { loader = Platform.X11.Glx.GetProcAddress; } else if (Configuration.RunningOnMacOS) { loader = Platform.MacOS.NS.GetAddress; } else { throw new PlatformNotSupportedException(); } return loader; } #endregion #region --- Creating a Graphics Context --- /// /// Creates an IGraphicsContext instance for the specified window. /// /// The GraphicsMode for the GraphicsContext. /// An IWindowInfo instance describing the parent window for this IGraphicsContext. /// The major OpenGL version number for this IGraphicsContext. /// The minor OpenGL version number for this IGraphicsContext. /// A bitwise collection of GraphicsContextFlags with specific options for this IGraphicsContext. /// A new IGraphicsContext instance. [Obsolete("Call new OpenTK.Graphics.GraphicsContext() directly, instead.")] public static IGraphicsContext CreateGraphicsContext( GraphicsMode mode, IWindowInfo window, int major, int minor, GraphicsContextFlags flags) { GraphicsContext context = new GraphicsContext(mode, window, major, minor, flags); context.MakeCurrent(window); (context as IGraphicsContextInternal).LoadAll(); return context; } #region CreateX11WindowInfo /// /// Constructs a new IWindowInfo instance for the X11 platform. /// /// The display connection. /// The screen. /// The handle for the window. /// The root window for screen. /// A pointer to a XVisualInfo structure obtained through XGetVisualInfo. /// A new IWindowInfo instance. public static IWindowInfo CreateX11WindowInfo(IntPtr display, int screen, IntPtr windowHandle, IntPtr rootWindow, IntPtr visualInfo) { Platform.X11.X11WindowInfo window = new OpenTK.Platform.X11.X11WindowInfo(); window.Display = display; window.Screen = screen; window.Handle = windowHandle; window.RootWindow = rootWindow; if (visualInfo != IntPtr.Zero) { window.VisualInfo = (X11.XVisualInfo)Marshal.PtrToStructure(visualInfo, typeof(X11.XVisualInfo)); } return window; } #endregion #region CreateWindowsWindowInfo /// /// Creates an IWindowInfo instance for the windows platform. /// /// The handle of the window. /// A new IWindowInfo instance. public static IWindowInfo CreateWindowsWindowInfo(IntPtr windowHandle) { return new OpenTK.Platform.Windows.WinWindowInfo(windowHandle, null); } #endregion #region CreateMacOSCarbonWindowInfo /// /// Creates an IWindowInfo instance for the Mac OS X platform. /// /// The handle of the window. /// Ignored. This is reserved for future use. /// Set to true if windowHandle corresponds to a System.Windows.Forms control. /// A new IWindowInfo instance. public static IWindowInfo CreateMacOSCarbonWindowInfo(IntPtr windowHandle, bool ownHandle, bool isControl) { return new OpenTK.Platform.MacOS.CarbonWindowInfo(windowHandle, false, isControl); } #endregion #region CreateDummyWindowInfo /// /// Creates an IWindowInfo instance for the dummy platform. /// /// A new IWindowInfo instance. public static IWindowInfo CreateDummyWindowInfo() { return new Dummy.DummyWindowInfo(); } #endregion #region CreateSdl2WindowInfo /// /// Creates an IWindowInfo instance for the windows platform. /// /// The handle of the window. /// A new IWindowInfo instance. public static IWindowInfo CreateSdl2WindowInfo(IntPtr windowHandle) { return new OpenTK.Platform.SDL2.Sdl2WindowInfo( windowHandle, null); } #endregion #endregion } }