/// <summary> /// Get the display associated with this Control. /// </summary> /// <returns> /// It returns an <see cref="IntPtr"/> valid for GLX functions as display parameter. /// </returns> protected IntPtr GetDisplay() { Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); if (xplatui != null) { // Get System.Windows.Forms display IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); KhronosApi.LogComment("System.Windows.Forms.XplatUIX11.DisplayHandle is 0x{0}", display.ToString("X")); if (display == IntPtr.Zero) { throw new InvalidOperationException("unable to connect to X server using XPlatUI"); } // Screen // _Screen = (int)xplatui.GetField("ScreenNo", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // KhronosApi.LogComment("System.Windows.Forms.XplatUIX11.ScreenNo is {0}", _Screen); return(display); } else { return(IntPtr.Zero); } }
/// <summary> /// Actually create this GraphicsWindow resources in Unix platform. /// </summary> /// <param name="surfaceFormat"> /// A <see cref="GraphicsBuffersFormat"/> used for selecting the most appropriate visual. /// </param> internal void PreCreateObjectX11(GraphicsBuffersFormat surfaceFormat) { if (surfaceFormat == null) { throw new ArgumentNullException("surfaceFormat"); } // Choose "best" pixel format matching with surface configuration _DeviceFormat = surfaceFormat.ChoosePixelFormat(_DeviceContext, ValidPixelFormat); sLog.Debug("Choosen frame buffer configuration: 0x{0} (visual 0x{1}).", _DeviceFormat.XFbConfig.ToString("X3"), _DeviceFormat.XVisualInfo.visualid.ToString("X3")); Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); if (xplatui == null) { throw new PlatformNotSupportedException("mono runtime version no supported"); } IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); IntPtr rootWindow = (IntPtr)xplatui.GetField("RootWindow", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); IntPtr colorMap = Glx.UnsafeNativeMethods.XCreateColormap(display, rootWindow, _DeviceFormat.XVisualInfo.visual, 0); // KhronosApi.LogFunction("XCreateColormap(0x{0}, {1}, {2}. 0) = {0}", display.ToString("X"), rootWindow.ToString("X"), _DeviceFormat.XVisualInfo.visual.ToString()); IntPtr customVisual = _DeviceFormat.XVisualInfo.visual; IntPtr origCustomVisual = (IntPtr)xplatui.GetField("CustomVisual", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); KhronosApi.LogComment("Set System.Windows.Forms.XplatUIX11.CustomVisual change from {0} to {1}", origCustomVisual.ToString("X"), customVisual.ToString("X")); xplatui.GetField("CustomVisual", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, customVisual); KhronosApi.LogComment("Create System.Windows.Forms.XplatUIX11.CustomColormap ({0})", colorMap.ToString("X")); xplatui.GetField("CustomColormap", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, colorMap); }
/// <summary> /// Get the display associated with this Control. /// </summary> /// <returns> /// It returns an <see cref="IntPtr"/> valid for GLX functions as display parameter. /// </returns> protected IntPtr GetDisplay() { switch (Platform.CurrentPlatformId) { case Platform.Id.WindowsNT: return(IntPtr.Zero); case Platform.Id.Linux: Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); if (xplatui == null) { throw new InvalidOperationException("no XPlatUI implementation"); } IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); KhronosApi.LogComment("System.Windows.Forms.XplatUIX11.DisplayHandle is 0x{0}", display.ToString("X")); if (display == IntPtr.Zero) { throw new InvalidOperationException("unable to connect to X server using XPlatUI"); } // Screen // _Screen = (int)xplatui.GetField("ScreenNo", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // KhronosApi.LogComment("System.Windows.Forms.XplatUIX11.ScreenNo is {0}", _Screen); return(display); default: throw new NotSupportedException("platform " + Platform.CurrentPlatformId + " not supported"); } }
/// <summary> /// Log an enumeration value. /// </summary> /// <param name="enumValue"> /// A <see cref="Int32"/> that specifies the enumeration value. /// </param> /// <returns> /// It returns a <see cref="String"/> that represents <paramref name="enumValue"/> as hexadecimal value. If the /// name of the enumeration value is detected, it returns the relative OpenGL specification name. /// </returns> protected static new string LogEnumName(int enumValue) { string enumName; if (_LogContext.EnumNames != null && _LogContext.EnumNames.TryGetValue(enumValue, out enumName)) return (enumName); else return (Gl.LogEnumName(enumValue) ?? KhronosApi.LogEnumName(enumValue)); }
/// <summary> /// Get a function pointer from the OpenGL driver. /// </summary> /// <param name="function"> /// A <see cref="String"/> that specifies the function name. /// </param> /// <returns> /// It returns an <see cref="IntPtr"/> that specifies the address of the function <paramref name="function"/>. /// </returns> public IntPtr GetOpenGLProcAddress(string function) { IntPtr procAddress = UnsafeNativeMethods.wglGetProcAddress(function); #if PLATFORM_LOG_ENABLED KhronosApi.LogFunction("wglGetProcAddress({0}) = 0x{1}", function, procAddress.ToString("X8")); #endif return(procAddress); }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting managed/unmanaged resources. /// </summary> /// <param name="disposing"> /// /// A <see cref="System.Boolean"/> indicating whether the disposition is requested explictly. /// </param> protected override void Dispose(bool disposing) { if (disposing) { if ((_OwnDisplay == true) && (Display != IntPtr.Zero)) { Glx.UnsafeNativeMethods.XCloseDisplay(Display); KhronosApi.LogFunction("XCloseDisplay({0})", Display.ToString("X")); } } }
/// <summary> /// Log an bitmask value. /// </summary> /// <param name="bitmaskName"> /// A <see cref="String"/> that specifies the enumeration bitmask name. /// </param> /// <param name="bitmaskValue"> /// A <see cref="Int32"/> that specifies the enumeration bitmask value. /// </param> /// <returns> /// It returns a <see cref="String"/> that represents <paramref name="bitmaskValue"/>. /// </returns> protected static new string LogEnumBitmask(string bitmaskName, long bitmaskValue) { Dictionary <long, String> bitmaskNames; if (_LogContext.EnumBitmasks.TryGetValue(bitmaskName, out bitmaskNames) == false) { return(KhronosApi.LogEnumBitmask(bitmaskName, bitmaskValue)); } return(KhronosApi.LogEnumBitmask(bitmaskValue, bitmaskNames)); }
/// <summary> /// Configure the logging system. /// </summary> public static void Configure(LogFlags flags) { // Configure base system XmlConfigurator.Configure(); // Log OpenGL method calls KhronosApi.RegisterApplicationLogDelegate(delegate(string format, object[] args) { _ProcedureLogger.Debug(format, args); }); // Enabe procedure logging KhronosApi.LogEnabled = true; }
/// <summary> /// Initializes the X11 multithreading. /// </summary> /// <exception cref='InvalidOperationException'> /// Is thrown when an operation cannot be performed. /// </exception> public static void InitializeMultithreading() { // Ensure to have X11 thread system initialized int initialized = Glx.UnsafeNativeMethods.XInitThreads(); KhronosApi.LogCommand("XInitThreads", initialized); if (initialized == 0) { throw new InvalidOperationException("platform does not support multithreading"); } _MultithreadingInitialized = true; }
/// <summary> /// Construct a <see cref="Derm.Render.XServerDeviceContext"/> class that opens the specified display. /// </summary> /// <param name="display"> /// A <see cref="System.IntpPtr"/> that will be argument of <see cref="Glx.XOpenDisplay"/>, indeed /// specifying the display to connect to. /// </param> /// <remarks> /// The property <see cref="WindowHandle"/> must be set to a valid value, since no window is created. The /// window handle shall be created using the display <see cref="Display"/>. /// </remarks> /// <exception cref='InvalidOperationException'> /// Exception thrown in the case it is not possible to connect with the display <paramref name="display"/>. /// </exception> public XServerDeviceContext(IntPtr display) { // Open display (follows DISPLAY environment variable) _Display = Glx.UnsafeNativeMethods.XOpenDisplay(display); KhronosApi.LogFunction("XOpenDisplay(0x0) = 0x{0}", _Display.ToString("X")); if (_Display == IntPtr.Zero) { throw new InvalidOperationException(String.Format("unable to connect to X server display {0}", display.ToInt32())); } // Need to close display _OwnDisplay = true; // Screen _Screen = Glx.UnsafeNativeMethods.XDefaultScreen(_Display); // Query GLX extensions QueryVersion(); }
/// <summary> /// Get a function pointer from a library, specified by handle. /// </summary> /// <param name="library"> /// A <see cref="IntPtr"/> which represents an opaque handle to the library containing the function. /// </param> /// <param name="function"> /// A <see cref="String"/> that specifies the function name. /// </param> /// <returns> /// It returns an <see cref="IntPtr"/> that specifies the address of the function <paramref name="function"/>. /// </returns> private IntPtr GetProcAddress(IntPtr library, string function) { if (library == IntPtr.Zero) { throw new ArgumentNullException("library"); } if (function == null) { throw new ArgumentNullException("function"); } IntPtr procAddress = UnsafeNativeMethods.Win32GetProcAddress(library, function); #if PLATFORM_LOG_ENABLED KhronosApi.LogFunction("GetProcAddress(0x{0}, {1}) = 0x{2}", library.ToString("X8"), function, procAddress.ToString("X8")); #endif return(procAddress); }
/// <summary> /// Query OpenGL implementation extensions. /// </summary> /// <param name="ctx"></param> /// <returns></returns> public static GraphicsCapabilities Query(GraphicsContext ctx, IDeviceContext deviceContext) { GraphicsCapabilities graphicsCapabilities = new GraphicsCapabilities(); KhronosApi.LogComment("Query OpenGL extensions."); #region Platform Extension Reload // Since at this point there's a current OpenGL context, it's possible to use // {glx|wgl}GetExtensionsString to retrieve platform specific extensions switch (Environment.OSVersion.Platform) { case PlatformID.Win32NT: case PlatformID.Win32Windows: case PlatformID.Win32S: case PlatformID.WinCE: // Wgl.SyncDelegates(); break; } #endregion // OpenGL extensions graphicsCapabilities._GlExtensions.Query(); // Windows OpenGL extensions WindowsDeviceContext windowsDeviceContext = deviceContext as WindowsDeviceContext; if (windowsDeviceContext != null) { graphicsCapabilities._WglExtensions.Query(windowsDeviceContext); } // GLX OpenGL extensions XServerDeviceContext xserverDeviceContext = deviceContext as XServerDeviceContext; if (xserverDeviceContext != null) { graphicsCapabilities._GlxExtensions.Query(xserverDeviceContext); } // Query implementation limits graphicsCapabilities._GraphicsLimits = GraphicsLimits.Query(graphicsCapabilities._GlExtensions); return(graphicsCapabilities); }
private IntPtr GetLibraryHandle(string libraryPath) { IntPtr libraryHandle; if (_LibraryHandles.TryGetValue(libraryPath, out libraryHandle) == false) { libraryHandle = UnsafeNativeMethods.LoadLibrary(libraryPath); #if PLATFORM_LOG_ENABLED KhronosApi.LogFunction("LoadLibrary({0}) = 0x{1}", libraryPath, libraryHandle.ToString("X8")); #endif _LibraryHandles.Add(libraryPath, libraryHandle); } if (libraryHandle == IntPtr.Zero) { throw new InvalidOperationException(String.Format("unable to load library at {0}", libraryPath)); } return(libraryHandle); }
/// <summary> /// Construct a fullscreen window. /// </summary> public VideoCoreWindow() { try { int width, height; KhronosApi.LogComment("Creating VideoCore IV native window"); if (Bcm.graphics_get_display_size(0 /* LCD */, out width, out height) < 0) { throw new InvalidOperationException("unable to get BCM display size"); } Bcm.VC_RECT_T dstRect = new Bcm.VC_RECT_T(0, 0, width, height); Bcm.VC_RECT_T srcRect = new Bcm.VC_RECT_T(0, 0, width << 16, height << 16); if ((_DispManxDisplay = Bcm.vc_dispmanx_display_open(0 /* LCD */)) == 0) { throw new InvalidOperationException("unable to open DispManX display"); } // Update - Add element uint updateHandle = Bcm.vc_dispmanx_update_start(0); _ElementHandle = Bcm.vc_dispmanx_element_add(updateHandle, _DispManxDisplay, 0, dstRect, 0, srcRect, 0, IntPtr.Zero, IntPtr.Zero, Bcm.DISPMANX_TRANSFORM_T.DISPMANX_NO_ROTATE); Bcm.vc_dispmanx_update_submit_sync(updateHandle); // Native window _NativeWindow = new EGL_DISPMANX_WINDOW_T(); _NativeWindow.element = _ElementHandle; _NativeWindow.width = width; _NativeWindow.height = height; // Keep native window pinned _NativeWindowLock = new MemoryLock(_NativeWindow); KhronosApi.LogComment("VideoCore IV Native Window is 0x{0}", _NativeWindowLock.Address.ToString("X")); } catch { Dispose(); throw; } }
/// <summary> /// Construct a <see cref="Derm.Render.XServerDeviceContext"/> class, initialized with the display of a control. /// </summary> /// <param name="control"> /// Control. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="control"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="control"/> handle is not created. /// </exception> /// <exception cref="PlatformNotSupportedException"> /// Exception thrown if the current assembly is not executed by a (supported) Mono runtime. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown if the current Mono runtime has not yet opened a display connection. /// </exception> public XServerDeviceContext(Control control) { if (control == null) { throw new ArgumentNullException("control"); } IntPtr controlHandle = control.Handle; if (control.IsHandleCreated == false) { throw new ArgumentException("handle not created", "control"); } Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); if (xplatui == null) { throw new PlatformNotSupportedException("mono runtime version no supported"); } // Get System.Windows.Forms display _Display = (IntPtr)xplatui.GetField("DisplayHandle", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); KhronosApi.LogComment("System.Windows.Forms.XplatUIX11.DisplayHandle is 0x{0}", _Display.ToString("X")); if (_Display == IntPtr.Zero) { throw new InvalidOperationException("unable to connect to X server using XPlatUI"); } // Screen _Screen = (int)xplatui.GetField("ScreenNo", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); KhronosApi.LogComment("System.Windows.Forms.XplatUIX11.ScreenNo is {0}", _Screen); // Window handle _WindowHandle = controlHandle; // Query GLX extensions QueryVersion(); }
/// <summary> /// Get the <see cref="Glx.XVisualInfo"/> set on the specified X window. /// </summary> /// <param name="xWindow"> /// The <see cref="IntPtr"/> that specifies the handle of the X window. /// </param> /// <returns> /// It returns the <see cref="Glx.XVisualInfo"/> set on <paramref name="xWindow"/>. /// </returns> private Glx.XVisualInfo GetVisualInfoFromXWindow(IntPtr xWindow) { Glx.XVisualInfo xVisualInfo; uint[] windowFBConfigId = new uint[1]; int screen = Glx.XDefaultScreen(_Display); // Get the FB configuration associated to the native window Glx.QueryDrawable(_Display, _WindowHandle, Glx.FBCONFIG_ID, windowFBConfigId); if (windowFBConfigId[0] == 0) { KhronosApi.LogComment("Glx.QueryDrawable cannot query Glx.FBCONFIG_ID. Query manually."); return(NativeWindow._InternalVisual); } unsafe { int[] attributes = new int[] { Glx.FBCONFIG_ID, (int)windowFBConfigId[0], 0, }; int[] choosenConfigCount = new int[1]; IntPtr *choosenConfigs = Glx.ChooseFBConfig(_Display, screen, attributes, choosenConfigCount); if (choosenConfigCount[0] == 0) { throw new InvalidOperationException("unable to find X Window visual configuration"); } IntPtr configId = *choosenConfigs; xVisualInfo = Glx.GetVisualFromFBConfig(_Display, configId); Glx.XFree((IntPtr)choosenConfigs); } return(xVisualInfo); }
/// <summary> /// Set the device pixel format. /// </summary> /// <param name="pixelFormat"> /// A <see cref="DevicePixelFormat"/> that specifies the pixel format to set. /// </param> public override void ChoosePixelFormat(DevicePixelFormat pixelFormat) { if (pixelFormat == null) { throw new ArgumentNullException("pixelFormat"); } int screen = Glx.XDefaultScreen(_Display); // Get basic visual Glx.XVisualInfo visual; IntPtr config; List <int> attributes = new List <int>(); if (pixelFormat.RenderWindow) { attributes.AddRange(new int[] { Glx.DRAWABLE_TYPE, (int)Glx.WINDOW_BIT }); } if (pixelFormat.RgbaUnsigned) { attributes.AddRange(new int[] { Glx.RENDER_TYPE, (int)Glx.RGBA_BIT }); } if (pixelFormat.RgbaFloat) { attributes.AddRange(new int[] { Glx.RENDER_TYPE, (int)Glx.RGBA_FLOAT_BIT_ARB }); } if (pixelFormat.DoubleBuffer) { attributes.AddRange(new int[] { Glx.DOUBLEBUFFER, Gl.TRUE }); } if (pixelFormat.ColorBits > 0) { switch (pixelFormat.ColorBits) { case 16: attributes.AddRange(new int[] { Glx.RED_SIZE, 5, Glx.GREEN_SIZE, 6, Glx.BLUE_SIZE, 8, Glx.ALPHA_SIZE, 5 }); break; case 24: attributes.AddRange(new int[] { Glx.RED_SIZE, 8, Glx.GREEN_SIZE, 8, Glx.BLUE_SIZE, 8 }); break; case 32: attributes.AddRange(new int[] { Glx.RED_SIZE, 8, Glx.GREEN_SIZE, 8, Glx.BLUE_SIZE, 8, Glx.ALPHA_SIZE, 8 }); break; default: if (pixelFormat.ColorBits < 16) { attributes.AddRange(new int[] { Glx.RED_SIZE, 1, Glx.GREEN_SIZE, 1, Glx.BLUE_SIZE, 1 }); } else { int bits = pixelFormat.ColorBits / 4; attributes.AddRange(new int[] { Glx.RED_SIZE, bits, Glx.GREEN_SIZE, bits, Glx.BLUE_SIZE, bits }); } break; } } if (pixelFormat.DepthBits > 0) { attributes.AddRange(new int[] { Glx.DEPTH_SIZE, pixelFormat.DepthBits }); } if (pixelFormat.StencilBits > 0) { attributes.AddRange(new int[] { Glx.STENCIL_SIZE, pixelFormat.StencilBits }); } attributes.Add(0); unsafe { int[] choosenConfigCount = new int[1]; IntPtr *choosenConfigs = Glx.ChooseFBConfig(_Display, screen, attributes.ToArray(), choosenConfigCount); if (choosenConfigCount[0] == 0) { throw new InvalidOperationException("unable to choose visual"); } config = *choosenConfigs; KhronosApi.LogComment("Choosen config is 0x{0}", config.ToString("X8")); visual = Glx.GetVisualFromFBConfig(_Display, config); KhronosApi.LogComment("Choosen visual is {0}", visual); Glx.XFree((IntPtr)choosenConfigs); } _FBConfig = config; _XVisualInfo = visual; IsPixelFormatSet = true; }
/// <summary> /// Default constructor. /// </summary> public NativeWindow(int x, int y, uint width, uint height) { try { // Open display if ((_Display = Glx.XOpenDisplay(IntPtr.Zero)) == IntPtr.Zero) { throw new InvalidOperationException("unable to connect to X server"); } Glx.XVisualInfo visual; IntPtr config; int[] attributes = new int[] { Glx.DRAWABLE_TYPE, (int)Glx.WINDOW_BIT, Glx.RENDER_TYPE, (int)Glx.RGBA_BIT, Glx.DOUBLEBUFFER, unchecked ((int)Glx.DONT_CARE), Glx.RED_SIZE, 1, Glx.GREEN_SIZE, 1, Glx.BLUE_SIZE, 1, 0 }; int screen = Glx.XDefaultScreen(_Display); // Get basic visual unsafe { int[] choosenConfigCount = new int[1]; IntPtr *choosenConfigs = Glx.ChooseFBConfig(_Display, screen, attributes, choosenConfigCount); if (choosenConfigCount[0] == 0) { throw new InvalidOperationException("unable to find basic visual"); } config = *choosenConfigs; KhronosApi.LogComment("Choosen config is 0x{0}", config.ToString("X8")); visual = Glx.GetVisualFromFBConfig(_Display, config); KhronosApi.LogComment("Choosen visual is {0}", visual); Glx.XFree((IntPtr)choosenConfigs); _InternalConfig = config; _InternalVisual = visual; } Glx.XSetWindowAttributes setWindowAttrs = new Glx.XSetWindowAttributes(); IntPtr rootWindow = Glx.XRootWindow(_Display, screen); ulong setWindowAttrFlags = /* CWBorderPixel | CWColormap | CWEventMask*/ (1L << 3) | (1L << 13) | (1L << 11); setWindowAttrs.border_pixel = IntPtr.Zero; setWindowAttrs.event_mask = /* StructureNotifyMask */new IntPtr(1L << 17); setWindowAttrs.colormap = Glx.XCreateColormap(_Display, rootWindow, visual.visual, /* AllocNone */ 0); if ((_Handle = Glx.XCreateWindow(_Display, rootWindow, x, y, (int)width, (int)height, 0, visual.depth, /* InputOutput */ 0, visual.visual, new UIntPtr(setWindowAttrFlags), ref setWindowAttrs)) == IntPtr.Zero) { throw new InvalidOperationException("unable to create window"); } // Assign FB configuration to window: essential to make CreateContext(IntPtr) working _GlxHandle = Glx.CreateWindow(_Display, config, _Handle, null); } catch { Dispose(); throw; } }
/// <summary> /// Query the OpenGL implementation limits. /// </summary> /// <param name="glExtensions"> /// A <see cref="Gl.Extensions"/> that specify the supported OpenGL extension by the current /// implementation. /// </param> /// <returns> /// It returns a <see cref="GraphicsLimits"/> that specify the current OpenGL implementation limits. /// </returns> /// <remarks> /// It is assumed to have a valid OpenGL context current on the calling thread. /// </remarks> public static GraphicsLimits Query(Gl.Extensions glExtensions) { if (glExtensions == null) { throw new ArgumentNullException("glExtensions"); } KhronosApi.LogComment("Query OpenGL implementation imits."); GraphicsLimits graphicsLimits = new GraphicsLimits(); FieldInfo[] graphicsLimitsFields = typeof(GraphicsLimits).GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in graphicsLimitsFields) { GraphicsLimitAttribute graphicsLimitAttribute = (GraphicsLimitAttribute)Attribute.GetCustomAttribute(field, typeof(GraphicsLimitAttribute)); Attribute[] graphicsExtensionAttributes = Attribute.GetCustomAttributes(field, typeof(KhronosApi.ExtensionAttribute)); MethodInfo getMethod; if (graphicsLimitAttribute == null) { continue; } // Check extension support if ((graphicsExtensionAttributes != null) && (graphicsExtensionAttributes.Length > 0)) { bool supported = Array.Exists(graphicsExtensionAttributes, delegate(Attribute item) { return(glExtensions.HasExtensions(((KhronosApi.ExtensionAttribute)item).ExtensionName)); }); if (supported == false) { continue; } } // Determine which method is used to get the OpenGL limit if (field.FieldType != typeof(String)) { if (field.FieldType.IsArray == true) { getMethod = typeof(Gl).GetMethod("Get", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32), field.FieldType }, null); } else { getMethod = typeof(Gl).GetMethod("Get", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32), field.FieldType.MakeByRefType() }, null); } } else { getMethod = typeof(Gl).GetMethod("GetString", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32) }, null); } if (getMethod != null) { if (field.FieldType != typeof(String)) { object obj; if (field.FieldType.IsArray == false) { obj = Activator.CreateInstance(field.FieldType); } else { obj = Array.CreateInstance(field.FieldType.GetElementType(), graphicsLimitAttribute.ArrayLenght); } object[] @params = new object[] { graphicsLimitAttribute.EnumValue, obj }; try { getMethod.Invoke(null, @params); field.SetValue(graphicsLimits, @params[1]); } catch (Exception) { } } else { try { string s = (string)getMethod.Invoke(null, new object[] { graphicsLimitAttribute.EnumValue }); field.SetValue(graphicsLimits, s); } catch (Exception) { } } } else { throw new InvalidOperationException("GraphicsLimits field " + field.Name + " doesn't have a OpenGL compatible type"); } string fieldValueString; object fieldValue = field.GetValue(graphicsLimits); if (fieldValue is Array) { StringBuilder sb = new StringBuilder(); sb.Append("{ "); if (((Array)fieldValue).Length > 0) { foreach (object arrayItem in (Array)fieldValue) { sb.AppendFormat("{0}, ", arrayItem); } sb.Remove(sb.Length - 2, 2); } sb.Append(" }"); fieldValueString = sb.ToString(); } else { fieldValueString = fieldValue.ToString(); } } return(graphicsLimits); }