Esempio n. 1
0
        public static IntPtr SelectFBConfig(IntPtr display, FramebufferFormat format)
        {
            List <int> visualAttribute = FramebufferFormatToVisualAttribute(format);

            IntPtr result = IntPtr.Zero;

            // TODO: make screen configurable?
            int screen = DefaultScreenLocked(display);

            int fbcount;

            unsafe
            {
                IntPtr *fbConfigs = GLX.ChooseFBConfig(display, screen, visualAttribute.ToArray(), out fbcount);

                if (fbcount > 0 && fbConfigs != null)
                {
                    result = *fbConfigs;

                    XFree((IntPtr)fbConfigs);
                }
            }

            return(result);
        }
Esempio n. 2
0
        public static OpenGLContextBase CreateOpenGLContext(FramebufferFormat framebufferFormat, int major, int minor, OpenGLContextFlags flags = OpenGLContextFlags.Default, bool directRendering = true, OpenGLContextBase shareContext = null)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                // TODO: detect X11/Wayland/DRI
                if (shareContext != null && !(shareContext is GLXOpenGLContext))
                {
                    throw new ContextException($"shared context must be of type {typeof(GLXOpenGLContext).Name}.");
                }

                return(new GLXOpenGLContext(framebufferFormat, major, minor, flags, directRendering, (GLXOpenGLContext)shareContext));
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                if (shareContext != null && !(shareContext is GLXOpenGLContext))
                {
                    throw new ContextException($"shared context must be of type {typeof(GLXOpenGLContext).Name}.");
                }

                return(new WGLOpenGLContext(framebufferFormat, major, minor, flags, directRendering, (WGLOpenGLContext)shareContext));
            }

            throw new NotImplementedException();
        }
Esempio n. 3
0
        public static IntPtr CreateContext(ref IntPtr windowHandle, FramebufferFormat framebufferFormat, int major, int minor, OpenGLContextFlags flags, bool directRendering, IntPtr shareContext)
        {
            EnsureInit();

            bool hasTempWindow = windowHandle == IntPtr.Zero;

            if (hasTempWindow)
            {
                windowHandle = Win32Helper.CreateNativeWindow(WindowStylesEx.WS_EX_OVERLAPPEDWINDOW,
                                                              WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN,
                                                              "SPB intermediary context",
                                                              0, 0, 1, 1);
            }

            IntPtr dcHandle = GetDC(windowHandle);

            int pixelFormat = FindPerfectFormat(dcHandle, framebufferFormat);

            // Perfect match not availaible, search for the closest
            if (pixelFormat == -1)
            {
                pixelFormat = FindClosestFormat(dcHandle, framebufferFormat);
            }

            if (pixelFormat == -1)
            {
                throw new PlatformException("Cannot find a valid pixel format");
            }

            PixelFormatDescriptor pfd = PixelFormatDescriptor.Create();

            int res = DescribePixelFormat(dcHandle, pixelFormat, Marshal.SizeOf <PixelFormatDescriptor>(), ref pfd);

            if (res == 0)
            {
                throw new PlatformException($"DescribePixelFormat failed: {Marshal.GetLastWin32Error()}");
            }

            res = SetPixelFormat(dcHandle, pixelFormat, ref pfd);

            if (res == 0)
            {
                throw new PlatformException($"DescribePixelFormat failed: {Marshal.GetLastWin32Error()}");
            }

            List <int> contextAttributes = GetContextCreationARBAttribute(major, minor, flags);

            IntPtr context = CreateContextAttribsArb(dcHandle, shareContext, contextAttributes.ToArray());

            ReleaseDC(windowHandle, dcHandle);

            if (hasTempWindow)
            {
                DestroyWindow(windowHandle);
            }

            return(context);
        }
Esempio n. 4
0
 public GLWidget(FramebufferFormat framebufferFormat, int major, int minor, OpenGLContextFlags flags = OpenGLContextFlags.Default, bool directRendering = true, OpenGLContextBase sharedContext = null)
 {
     FramebufferFormat = framebufferFormat;
     GLVersionMajor    = major;
     GLVersionMinor    = minor;
     ContextFlags      = flags;
     DirectRendering   = directRendering;
     SharedContext     = sharedContext;
 }
Esempio n. 5
0
 public OpenGLContextBase(FramebufferFormat framebufferFormat, int major, int minor, OpenGLContextFlags flags, bool directRendering, OpenGLContextBase shareContext)
 {
     FramebufferFormat = framebufferFormat;
     Major             = major;
     Minor             = minor;
     Flags             = flags;
     DirectRendering   = directRendering;
     ShareContext      = shareContext;
 }
Esempio n. 6
0
        public static GLXWindow CreateGLXWindow(NativeHandle display, FramebufferFormat format, int x, int y, int width, int height)
        {
            IntPtr fbConfig = GLXHelper.SelectFBConfig(display.RawHandle, format);

            unsafe
            {
                X11.XVisualInfo *visualInfo;

                if (fbConfig != IntPtr.Zero)
                {
                    visualInfo = GLX.GLX.GetVisualFromFBConfig(display.RawHandle, fbConfig);
                }
                else
                {
                    // TODO: support old visual selection
                    throw new NotImplementedException();
                }


                if (visualInfo == null)
                {
                    throw new NotImplementedException();
                }

                // make screen configurable?
                int screen = X11.DefaultScreenLocked(display.RawHandle);

                IntPtr rootWindow = X11.RootWindow(display.RawHandle, screen);

                X11.XSetWindowAttributes attributes = new X11.XSetWindowAttributes
                {
                    BackgroundPixel = IntPtr.Zero,
                    BorderPixel     = IntPtr.Zero,
                    ColorMap        = X11.CreateColormap(display.RawHandle, rootWindow, visualInfo->Visual, 0)
                };
                // TODO: events

                X11.SetWindowValueMask windowValueMask = X11.SetWindowValueMask.ColorMap | X11.SetWindowValueMask.EventMask | X11.SetWindowValueMask.BackPixel | X11.SetWindowValueMask.BorderPixel;

                X11.XSetWindowAttributes *attributesPtr = &attributes;

                IntPtr rawWindowHandle = X11.CreateWindow(display.RawHandle, rootWindow, x, y, width, height, 0, visualInfo->Depth, (int)X11.CreateWindowArgs.InputOutput, visualInfo->Visual, (IntPtr)windowValueMask, (IntPtr)attributesPtr);

                if (rawWindowHandle == IntPtr.Zero)
                {
                    throw new ApplicationException("Cannot create X window!");
                }

                return(new GLXWindow(display, new NativeHandle(rawWindowHandle)));
            }
        }
Esempio n. 7
0
        public static SwappableNativeWindowBase CreateOpenGLWindow(FramebufferFormat format, int x, int y, int width, int height)
        {
            if (OperatingSystem.IsLinux())
            {
                // TODO: detect X11/Wayland/DRI
                return(X11Helper.CreateGLXWindow(new NativeHandle(X11.X11.DefaultDisplay), format, x, y, width, height));
            }
            else if (OperatingSystem.IsWindows())
            {
                // TODO pass format
                return(Win32Helper.CreateWindowForWGL(x, y, width, height));
            }

            throw new NotImplementedException();
        }
Esempio n. 8
0
        public static NativeWindowBase CreateWindow(FramebufferFormat format, int x, int y, int width, int height)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                // TODO: detect X11/Wayland/DRI
                return(X11Helper.CreateGLXWindow(new NativeHandle(X11.X11.DefaultDisplay), format, x, y, width, height));
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // TODO pass format
                return(Win32Helper.CreateWindowForWGL(x, y, width, height));
            }

            throw new NotImplementedException();
        }
Esempio n. 9
0
        private static int FindPerfectFormat(IntPtr dcHandle, FramebufferFormat format)
        {
            List <int> attributes = FramebufferFormatToPixelFormatAttributes(format);

            int[] formats = new int[1];

            if (!ChoosePixelFormatArb(dcHandle, attributes.ToArray(), null, formats.Length, formats, out int numFormat))
            {
                throw new PlatformException($"wglChoosePixelFormatARB failed: {Marshal.GetLastWin32Error()}");
            }

            if (numFormat == 0)
            {
                return(-1);
            }

            return(formats[0]);
        }
Esempio n. 10
0
        public static List <int> FramebufferFormatToVisualAttribute(FramebufferFormat format)
        {
            List <int> result = new List <int>();

            if (format.Color.BitsPerPixel > 0)
            {
                result.Add((int)GLX.Attribute.RENDER_TYPE);
                result.Add((int)GLX.RenderTypeMask.RGBA_BIT);

                result.Add((int)GLX.Attribute.RED_SIZE);
                result.Add(format.Color.Red);

                result.Add((int)GLX.Attribute.GREEN_SIZE);
                result.Add(format.Color.Green);

                result.Add((int)GLX.Attribute.BLUE_SIZE);
                result.Add(format.Color.Blue);

                result.Add((int)GLX.Attribute.ALPHA_SIZE);
                result.Add(format.Color.Alpha);
            }

            if (format.DepthBits > 0)
            {
                result.Add((int)GLX.Attribute.DEPTH_SIZE);
                result.Add(format.DepthBits);
            }


            if (format.Buffers > 1)
            {
                result.Add((int)GLX.Attribute.DOUBLEBUFFER);
                result.Add(1);
            }

            if (format.Stereo)
            {
                result.Add((int)GLX.Attribute.STENCIL_SIZE);
                result.Add(format.Stereo ? 1 : 0);
            }

            if (format.Accumulator.BitsPerPixel > 0)
            {
                result.Add((int)GLX.Attribute.ACCUM_ALPHA_SIZE);
                result.Add(format.Accumulator.Alpha);

                result.Add((int)GLX.Attribute.ACCUM_BLUE_SIZE);
                result.Add(format.Accumulator.Blue);

                result.Add((int)GLX.Attribute.ACCUM_GREEN_SIZE);
                result.Add(format.Accumulator.Green);

                result.Add((int)GLX.Attribute.ACCUM_RED_SIZE);
                result.Add(format.Accumulator.Red);
            }

            if (format.Samples > 0)
            {
                result.Add((int)GLX.Attribute.SAMPLE_BUFFERS);
                result.Add(1);

                result.Add((int)GLX.Attribute.SAMPLES);
                result.Add((int)format.Samples);
            }

            if (format.Stereo)
            {
                result.Add((int)GLX.Attribute.STEREO);
                result.Add(1);
            }

            // NOTE: Format is key: value, nothing in the spec specify if the end marker follow or not this format.
            // BODY: As such, we add an extra 0 just to be sure we don't break anything.
            result.Add(0);
            result.Add(0);

            return(result);
        }
Esempio n. 11
0
 public WGLOpenGLContext(FramebufferFormat framebufferFormat, int major, int minor, OpenGLContextFlags flags = OpenGLContextFlags.Default, bool directRendering = true, WGLOpenGLContext shareContext = null) : base(framebufferFormat, major, minor, flags, directRendering, shareContext)
 {
     _deviceContext = IntPtr.Zero;
     _window        = null;
 }
Esempio n. 12
0
        private static int FindClosestFormat(IntPtr dcHandle, FramebufferFormat format)
        {
            const int WGL_NO_ACCELERATION_ARB = 0x2025;

            int[] formatValue = new int[1];

            if (!GetPixelFormatAttribivARB(dcHandle, 1, 0, 1, new int[1] {
                (int)WGL.ARB.Attribute.WGL_NUMBER_PIXEL_FORMATS_ARB
            }, formatValue))
            {
                throw new PlatformException($"wglGetPixelFormatAttribivARB failed: {Marshal.GetLastWin32Error()}");
            }

            int formatCount = formatValue[0];

            List <int> tempAttributeList = new List <int>();

            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_SUPPORT_OPENGL_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_DRAW_TO_WINDOW_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_PIXEL_TYPE_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_ACCELERATION_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_RED_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_GREEN_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_BLUE_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_ALPHA_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_DEPTH_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_STENCIL_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_ACCUM_RED_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_ACCUM_GREEN_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_ACCUM_BLUE_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_ACCUM_ALPHA_BITS_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_STEREO_ARB);
            tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_DOUBLE_BUFFER_ARB);

            if (Extensions.Contains("WGL_ARB_multisample"))
            {
                tempAttributeList.Add((int)WGL.ARB.Attribute.WGL_SAMPLES_ARB);
            }

            int[] attributes = tempAttributeList.ToArray();

            int[] values = new int[Unsafe.SizeOf <AttributeInformation>() / sizeof(int)];

            int  closestIndex            = int.MaxValue;
            uint leastMissing            = uint.MaxValue;
            uint leastRawColorDifference = uint.MaxValue;
            uint leastExtraDifference    = uint.MaxValue;

            for (int index = 0; index < formatCount; index++)
            {
                if (!GetPixelFormatAttribivARB(dcHandle, index + 1, 0, (uint)attributes.Length, attributes, values))
                {
                    throw new PlatformException($"wglGetPixelFormatAttribivARB failed: {Marshal.GetLastWin32Error()}");
                }

                AttributeInformation information = MemoryMarshal.Cast <int, AttributeInformation>(values)[0];

                if (information.SupportOpenGL != 0 && information.Acceleration != WGL_NO_ACCELERATION_ARB)
                {
                    if (format.Stereo && information.Stereo == 0)
                    {
                        continue;
                    }

                    if (format.Buffers > 1 && information.DoubleBuffer == 0)
                    {
                        continue;
                    }

                    // Based on glfw3 algorithm.
                    information.CompareWithDesiredFormat(format, out uint missing, out uint rawColorDifference, out uint extraDifference);

                    if (missing < leastMissing)
                    {
                        closestIndex = index;
                    }
                    else if (missing == leastMissing)
                    {
                        if ((rawColorDifference < leastRawColorDifference) || ((rawColorDifference == leastRawColorDifference) && (extraDifference < leastExtraDifference)))
                        {
                            closestIndex = index;
                        }
                    }


                    if (closestIndex == index)
                    {
                        leastMissing            = missing;
                        leastRawColorDifference = rawColorDifference;
                        leastExtraDifference    = extraDifference;
                    }
                }
            }

            if (closestIndex == int.MaxValue)
            {
                closestIndex = -1;
            }

            return(closestIndex);
        }
Esempio n. 13
0
            public void CompareWithDesiredFormat(FramebufferFormat desiredFormat, out uint miss, out uint rawColorDifference, out uint extraDifference)
            {
                miss = 0;

                if (desiredFormat.StencilBits > 0 && StencilBits == 0)
                {
                    miss++;
                }

                if (desiredFormat.DepthBits > 0 && DepthBits == 0)
                {
                    miss++;
                }

                if (desiredFormat.Color.Alpha > 0 && AlphaBits == 0)
                {
                    miss++;
                }

                if (desiredFormat.Samples > 0 && Samples == 0)
                {
                    miss++;
                }

                rawColorDifference = 0;

                if (desiredFormat.Color.BitsPerPixel > 0)
                {
                    rawColorDifference = (uint)((desiredFormat.Color.Red - RedBits) * (desiredFormat.Color.Red - RedBits)
                                                + (desiredFormat.Color.Blue - BlueBits) * (desiredFormat.Color.Blue - BlueBits)
                                                + (desiredFormat.Color.Green - GreenBits) * (desiredFormat.Color.Green - GreenBits));
                }

                extraDifference = 0;

                if (desiredFormat.StencilBits > 0)
                {
                    extraDifference += (uint)((desiredFormat.StencilBits - StencilBits) * (desiredFormat.StencilBits - StencilBits));
                }

                if (desiredFormat.DepthBits > 0)
                {
                    extraDifference += (uint)((desiredFormat.DepthBits - DepthBits) * (desiredFormat.DepthBits - DepthBits));
                }

                if (desiredFormat.Accumulator.BitsPerPixel > 0)
                {
                    extraDifference += (uint)((desiredFormat.Accumulator.Red - AccumRedBits) * (desiredFormat.Accumulator.Red - AccumRedBits)
                                              + (desiredFormat.Accumulator.Blue - AccumBlueBits) * (desiredFormat.Accumulator.Blue - AccumBlueBits)
                                              + (desiredFormat.Accumulator.Green - AccumGreenBits) * (desiredFormat.Accumulator.Green - AccumGreenBits));
                }

                if (desiredFormat.Accumulator.Alpha > 0)
                {
                    extraDifference += (uint)((desiredFormat.Accumulator.Alpha - AccumAlphaBits) * (desiredFormat.Accumulator.Alpha - AccumAlphaBits));
                }

                if (desiredFormat.Samples > 0)
                {
                    extraDifference += (uint)(((int)desiredFormat.Samples - Samples) * ((int)desiredFormat.Samples - Samples));
                }
            }
Esempio n. 14
0
        private static List <int> FramebufferFormatToPixelFormatAttributes(FramebufferFormat format)
        {
            const int  WGL_FULL_ACCELERATION_ARB = 0x2027;
            List <int> result = new List <int>();

            // Full acceleration required
            result.Add((int)WGL.ARB.Attribute.WGL_ACCELERATION_ARB);
            result.Add(WGL_FULL_ACCELERATION_ARB);

            // We use OpenGL so we need it...
            result.Add((int)WGL.ARB.Attribute.WGL_SUPPORT_OPENGL_ARB);
            result.Add(1);

            result.Add((int)WGL.ARB.Attribute.WGL_DRAW_TO_WINDOW_ARB);
            result.Add(1);

            if (format.Color.BitsPerPixel > 0)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_RED_BITS_ARB);
                result.Add(format.Color.Red);

                result.Add((int)WGL.ARB.Attribute.WGL_GREEN_BITS_ARB);
                result.Add(format.Color.Green);

                result.Add((int)WGL.ARB.Attribute.WGL_BLUE_BITS_ARB);
                result.Add(format.Color.Blue);

                result.Add((int)WGL.ARB.Attribute.WGL_ALPHA_BITS_ARB);
                result.Add(format.Color.Alpha);
            }

            if (format.DepthBits > 0)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_DEPTH_BITS_ARB);
                result.Add(format.DepthBits);
            }


            if (format.Buffers > 1)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_DOUBLE_BUFFER_ARB);
                result.Add(1);
            }

            if (format.StencilBits > 0)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_STENCIL_BITS_ARB);
                result.Add(format.StencilBits);
            }

            if (format.Accumulator.BitsPerPixel > 0)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_ACCUM_ALPHA_BITS_ARB);
                result.Add(format.Accumulator.Alpha);

                result.Add((int)WGL.ARB.Attribute.WGL_ACCUM_BLUE_BITS_ARB);
                result.Add(format.Accumulator.Blue);

                result.Add((int)WGL.ARB.Attribute.WGL_ACCUM_GREEN_BITS_ARB);
                result.Add(format.Accumulator.Green);

                result.Add((int)WGL.ARB.Attribute.WGL_ACCUM_RED_BITS_ARB);
                result.Add(format.Accumulator.Red);
            }

            if (format.Samples > 0)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_DOUBLE_BUFFER_ARB);
                result.Add(1);
            }

            if (format.Stereo)
            {
                result.Add((int)WGL.ARB.Attribute.WGL_STEREO_ARB);
                result.Add(format.Stereo ? 1 : 0);
            }

            // NOTE: Format is key: value, nothing in the spec specify if the end marker follow or not this format.
            // BODY: As such, we add an extra 0 just to be sure we don't break anything.
            result.Add(0);
            result.Add(0);

            return(result);
        }