/// <summary> /// Creates an OpenGL context from a Unix/Linux platform. /// </summary> /// <returns> /// A <see cref="IDeviceContext"/> that specify the device context. /// </returns> private static IntPtr CreateX11SimpleContext(IDeviceContext rDevice) { XServerDeviceContext x11DeviceCtx = (XServerDeviceContext)rDevice; IntPtr rContext; using (Glx.XLock xLock = new Glx.XLock(x11DeviceCtx.Display)) { int[] attributes = new int[] { Glx.RENDER_TYPE, (int)Glx.RGBA_BIT, 0 }; // Get basic visual unsafe { int[] choosenConfigCount = new int[1]; IntPtr *choosenConfigs = Glx.ChooseFBConfig(x11DeviceCtx.Display, x11DeviceCtx.Screen, attributes, choosenConfigCount); if (choosenConfigCount[0] == 0) { throw new InvalidOperationException("unable to find basic visual"); } IntPtr choosenConfig = *choosenConfigs; x11DeviceCtx.XVisualInfo = Glx.GetVisualFromFBConfig(x11DeviceCtx.Display, choosenConfig); x11DeviceCtx.FBConfig = choosenConfig; Glx.UnsafeNativeMethods.XFree((IntPtr)choosenConfigs); } // Create direct context rContext = x11DeviceCtx.CreateContext(IntPtr.Zero); if (rContext == IntPtr.Zero) { // Fallback to not direct context rContext = Glx.CreateContext(x11DeviceCtx.Display, x11DeviceCtx.XVisualInfo, IntPtr.Zero, false); } if (rContext == IntPtr.Zero) { throw new InvalidOperationException("unable to create context"); } return(rContext); } }
/// <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; } }