/// <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;
                }
            }