Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1452 | chris | 1 | #region --- License --- |
| 2 | /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos |
||
| 3 | * See license.txt for license info |
||
| 4 | */ |
||
| 5 | #endregion |
||
| 6 | |||
| 7 | #region --- Using Directives --- |
||
| 8 | |||
| 9 | using System; |
||
| 10 | using System.Collections.Generic; |
||
| 11 | using System.Text; |
||
| 12 | using System.Windows.Forms; |
||
| 13 | using System.Runtime.InteropServices; |
||
| 14 | using System.Reflection; |
||
| 15 | using System.Diagnostics; |
||
| 16 | using OpenTK.Graphics; |
||
| 17 | |||
| 18 | #endregion |
||
| 19 | |||
| 20 | namespace OpenTK.Platform |
||
| 21 | { |
||
| 22 | /// <summary> |
||
| 23 | /// Provides cross-platform utilities to help interact with the underlying platform. |
||
| 24 | /// </summary> |
||
| 25 | public static class Utilities |
||
| 26 | { |
||
| 27 | #region internal static bool ThrowOnX11Error |
||
| 28 | |||
| 29 | static bool throw_on_error; |
||
| 30 | internal static bool ThrowOnX11Error |
||
| 31 | { |
||
| 32 | get { return throw_on_error; } |
||
| 33 | set |
||
| 34 | { |
||
| 35 | if (value && !throw_on_error) |
||
| 36 | { |
||
| 37 | Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms") |
||
| 38 | .GetField("ErrorExceptions", System.Reflection.BindingFlags.Static | |
||
| 39 | System.Reflection.BindingFlags.NonPublic) |
||
| 40 | .SetValue(null, true); |
||
| 41 | throw_on_error = true; |
||
| 42 | } |
||
| 43 | else if (!value && throw_on_error) |
||
| 44 | { |
||
| 45 | Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms") |
||
| 46 | .GetField("ErrorExceptions", System.Reflection.BindingFlags.Static | |
||
| 47 | System.Reflection.BindingFlags.NonPublic) |
||
| 48 | .SetValue(null, false); |
||
| 49 | throw_on_error = false; |
||
| 50 | } |
||
| 51 | } |
||
| 52 | } |
||
| 53 | |||
| 54 | #endregion |
||
| 55 | |||
| 56 | #region internal static void LoadExtensions(Type type) |
||
| 57 | |||
| 58 | delegate Delegate LoadDelegateFunction(string name, Type signature); |
||
| 59 | |||
| 60 | /// <internal /> |
||
| 61 | /// <summary>Loads all extensions for the specified class. This function is intended |
||
| 62 | /// for OpenGL, Wgl, Glx, OpenAL etc.</summary> |
||
| 63 | /// <param name="type">The class to load extensions for.</param> |
||
| 64 | /// <remarks> |
||
| 65 | /// <para>The Type must contain a nested class called "Delegates".</para> |
||
| 66 | /// <para> |
||
| 67 | /// The Type must also implement a static function called LoadDelegate with the |
||
| 68 | /// following signature: |
||
| 69 | /// <code>static Delegate LoadDelegate(string name, Type signature)</code> |
||
| 70 | /// </para> |
||
| 71 | /// <para>This function allocates memory.</para> |
||
| 72 | /// </remarks> |
||
| 73 | internal static void LoadExtensions(Type type) |
||
| 74 | { |
||
| 75 | // Using reflection is more than 3 times faster than directly loading delegates on the first |
||
| 76 | // run, probably due to code generation overhead. Subsequent runs are faster with direct loading |
||
| 77 | // than with reflection, but the first time is more significant. |
||
| 78 | |||
| 79 | int supported = 0; |
||
| 80 | Type extensions_class = type.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 81 | if (extensions_class == null) |
||
| 82 | throw new InvalidOperationException("The specified type does not have any loadable extensions."); |
||
| 83 | |||
| 84 | FieldInfo[] delegates = extensions_class.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 85 | if (delegates == null) |
||
| 86 | throw new InvalidOperationException("The specified type does not have any loadable extensions."); |
||
| 87 | |||
| 88 | MethodInfo load_delegate_method_info = type.GetMethod("LoadDelegate", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 89 | if (load_delegate_method_info == null) |
||
| 90 | throw new InvalidOperationException(type.ToString() + " does not contain a static LoadDelegate method."); |
||
| 91 | LoadDelegateFunction LoadDelegate = (LoadDelegateFunction)Delegate.CreateDelegate( |
||
| 92 | typeof(LoadDelegateFunction), load_delegate_method_info); |
||
| 93 | |||
| 94 | Debug.Write("Load extensions for " + type.ToString() + "... "); |
||
| 95 | |||
| 96 | System.Diagnostics.Stopwatch time = new System.Diagnostics.Stopwatch(); |
||
| 97 | time.Reset(); |
||
| 98 | time.Start(); |
||
| 99 | |||
| 100 | foreach (FieldInfo f in delegates) |
||
| 101 | { |
||
| 102 | Delegate d = LoadDelegate(f.Name, f.FieldType); |
||
| 103 | if (d != null) |
||
| 104 | ++supported; |
||
| 105 | |||
| 106 | f.SetValue(null, d); |
||
| 107 | } |
||
| 108 | |||
| 109 | FieldInfo rebuildExtensionList = type.GetField("rebuildExtensionList", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 110 | if (rebuildExtensionList != null) |
||
| 111 | rebuildExtensionList.SetValue(null, true); |
||
| 112 | |||
| 113 | time.Stop(); |
||
| 114 | Debug.Print("{0} extensions loaded in {1} ms.", supported, time.ElapsedMilliseconds); |
||
| 115 | time.Reset(); |
||
| 116 | } |
||
| 117 | |||
| 118 | #endregion |
||
| 119 | |||
| 120 | #region internal static bool TryLoadExtension(Type type, string extension) |
||
| 121 | |||
| 122 | /// <internal /> |
||
| 123 | /// <summary>Loads the specified extension for the specified class. This function is intended |
||
| 124 | /// for OpenGL, Wgl, Glx, OpenAL etc.</summary> |
||
| 125 | /// <param name="type">The class to load extensions for.</param> |
||
| 126 | /// <param name="extension">The extension to load.</param> |
||
| 127 | /// <remarks> |
||
| 128 | /// <para>The Type must contain a nested class called "Delegates".</para> |
||
| 129 | /// <para> |
||
| 130 | /// The Type must also implement a static function called LoadDelegate with the |
||
| 131 | /// following signature: |
||
| 132 | /// <code>static Delegate LoadDelegate(string name, Type signature)</code> |
||
| 133 | /// </para> |
||
| 134 | /// <para>This function allocates memory.</para> |
||
| 135 | /// </remarks> |
||
| 136 | internal static bool TryLoadExtension(Type type, string extension) |
||
| 137 | { |
||
| 138 | Type extensions_class = type.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 139 | if (extensions_class == null) |
||
| 140 | { |
||
| 141 | Debug.Print(type.ToString(), " does not contain extensions."); |
||
| 142 | return false; |
||
| 143 | } |
||
| 144 | |||
| 145 | LoadDelegateFunction LoadDelegate = (LoadDelegateFunction)Delegate.CreateDelegate(typeof(LoadDelegateFunction), |
||
| 146 | type.GetMethod("LoadDelegate", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)); |
||
| 147 | if (LoadDelegate == null) |
||
| 148 | { |
||
| 149 | Debug.Print(type.ToString(), " does not contain a static LoadDelegate method."); |
||
| 150 | return false; |
||
| 151 | } |
||
| 152 | |||
| 153 | FieldInfo f = extensions_class.GetField(extension, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 154 | if (f == null) |
||
| 155 | { |
||
| 156 | Debug.Print("Extension \"", extension, "\" not found in ", type.ToString()); |
||
| 157 | return false; |
||
| 158 | } |
||
| 159 | |||
| 160 | Delegate old = f.GetValue(null) as Delegate; |
||
| 161 | Delegate @new = LoadDelegate(f.Name, f.FieldType); |
||
| 162 | if ((old != null ? old.Target : null) != (@new != null ? @new.Target : null)) |
||
| 163 | { |
||
| 164 | f.SetValue(null, @new); |
||
| 165 | FieldInfo rebuildExtensionList = type.GetField("rebuildExtensionList", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); |
||
| 166 | if (rebuildExtensionList != null) |
||
| 167 | rebuildExtensionList.SetValue(null, true); |
||
| 168 | } |
||
| 169 | return @new != null; |
||
| 170 | } |
||
| 171 | |||
| 172 | #endregion |
||
| 173 | |||
| 174 | #region --- Creating a Graphics Context --- |
||
| 175 | |||
| 176 | /// <summary> |
||
| 177 | /// Creates an IGraphicsContext instance for the specified window. |
||
| 178 | /// </summary> |
||
| 179 | /// <param name="mode">The GraphicsMode for the GraphicsContext.</param> |
||
| 180 | /// <param name="window">An IWindowInfo instance describing the parent window for this IGraphicsContext.</param> |
||
| 181 | /// <param name="major">The major OpenGL version number for this IGraphicsContext.</param> |
||
| 182 | /// <param name="minor">The minor OpenGL version number for this IGraphicsContext.</param> |
||
| 183 | /// <param name="flags">A bitwise collection of GraphicsContextFlags with specific options for this IGraphicsContext.</param> |
||
| 184 | /// <returns>A new IGraphicsContext instance.</returns> |
||
| 185 | [Obsolete("Call new OpenTK.Graphics.GraphicsContext() directly, instead.")] |
||
| 186 | public static IGraphicsContext CreateGraphicsContext( |
||
| 187 | GraphicsMode mode, IWindowInfo window, |
||
| 188 | int major, int minor, GraphicsContextFlags flags) |
||
| 189 | { |
||
| 190 | GraphicsContext context = new GraphicsContext(mode, window, major, minor, flags); |
||
| 191 | context.MakeCurrent(window); |
||
| 192 | |||
| 193 | (context as IGraphicsContextInternal).LoadAll(); |
||
| 194 | |||
| 195 | return context; |
||
| 196 | } |
||
| 197 | |||
| 198 | #region CreateX11WindowInfo |
||
| 199 | |||
| 200 | /// <summary> |
||
| 201 | /// Constructs a new IWindowInfo instance for the X11 platform. |
||
| 202 | /// </summary> |
||
| 203 | /// <param name="display">The display connection.</param> |
||
| 204 | /// <param name="screen">The screen.</param> |
||
| 205 | /// <param name="windowHandle">The handle for the window.</param> |
||
| 206 | /// <param name="rootWindow">The root window for screen.</param> |
||
| 207 | /// <param name="visualInfo">A pointer to a XVisualInfo structure obtained through XGetVisualInfo.</param> |
||
| 208 | /// <returns>A new IWindowInfo instance.</returns> |
||
| 209 | public static IWindowInfo CreateX11WindowInfo(IntPtr display, int screen, IntPtr windowHandle, IntPtr rootWindow, IntPtr visualInfo) |
||
| 210 | { |
||
| 211 | Platform.X11.X11WindowInfo window = new OpenTK.Platform.X11.X11WindowInfo(); |
||
| 212 | window.Display = display; |
||
| 213 | window.Screen = screen; |
||
| 214 | window.WindowHandle = windowHandle; |
||
| 215 | window.RootWindow = rootWindow; |
||
| 216 | window.VisualInfo = (X11.XVisualInfo)Marshal.PtrToStructure(visualInfo, typeof(X11.XVisualInfo)); |
||
| 217 | |||
| 218 | return window; |
||
| 219 | } |
||
| 220 | |||
| 221 | #endregion |
||
| 222 | |||
| 223 | #region CreateWindowsWindowInfo |
||
| 224 | |||
| 225 | /// <summary> |
||
| 226 | /// Creates an IWindowInfo instance for the windows platform. |
||
| 227 | /// </summary> |
||
| 228 | /// <param name="windowHandle">The handle of the window.</param> |
||
| 229 | /// <returns>A new IWindowInfo instance.</returns> |
||
| 230 | public static IWindowInfo CreateWindowsWindowInfo(IntPtr windowHandle) |
||
| 231 | { |
||
| 232 | return new OpenTK.Platform.Windows.WinWindowInfo(windowHandle, null); |
||
| 233 | } |
||
| 234 | |||
| 235 | #endregion |
||
| 236 | |||
| 237 | #region CreateMacOSCarbonWindowInfo |
||
| 238 | |||
| 239 | /// <summary> |
||
| 240 | /// Creates an IWindowInfo instance for the Mac OS X platform. |
||
| 241 | /// </summary> |
||
| 242 | /// <param name="windowHandle">The handle of the window.</param> |
||
| 243 | /// <param name="ownHandle">Ignored. This is reserved for future use.</param> |
||
| 244 | /// <param name="isControl">Set to true if windowHandle corresponds to a System.Windows.Forms control.</param> |
||
| 245 | /// <returns>A new IWindowInfo instance.</returns> |
||
| 246 | public static IWindowInfo CreateMacOSCarbonWindowInfo(IntPtr windowHandle, bool ownHandle, bool isControl) |
||
| 247 | { |
||
| 248 | return new OpenTK.Platform.MacOS.CarbonWindowInfo(windowHandle, false, isControl); |
||
| 249 | } |
||
| 250 | |||
| 251 | #endregion |
||
| 252 | |||
| 253 | #region CreateDummyWindowInfo |
||
| 254 | |||
| 255 | /// <summary> |
||
| 256 | /// Creates an IWindowInfo instance for the dummy platform. |
||
| 257 | /// </summary> |
||
| 258 | /// <returns>A new IWindowInfo instance.</returns> |
||
| 259 | public static IWindowInfo CreateDummyWindowInfo() |
||
| 260 | { |
||
| 261 | return new Dummy.DummyWindowInfo(); |
||
| 262 | } |
||
| 263 | |||
| 264 | #endregion |
||
| 265 | |||
| 266 | #endregion |
||
| 267 | |||
| 268 | |||
| 269 | } |
||
| 270 | } |