Beispiel #1
0
        protected override void Dispose(bool manual)
        {
            if (egl_display != IntPtr.Zero)
            {
                Debug.Print("[KMS] Terminating EGL.");
                Egl.Terminate(egl_display);
                egl_display = IntPtr.Zero;
            }
            if (gbm_device != IntPtr.Zero)
            {
                Debug.Print("[KMS] Destroying GBM device.");
                Gbm.DestroyDevice(gbm_device);
                gbm_device = IntPtr.Zero;
            }
            if (_fd >= 0)
            {
                Debug.Print("[KMS] Closing GPU fd.");
                Libc.close(_fd);
            }

            base.Dispose(manual);
        }
Beispiel #2
0
        private static EGLDisplay InitializeDisplay()
        {
            int[] defaultDisplayAttributes =
            {
                // These are the default display attributes, used to request ANGLE's D3D11 renderer.
                // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
                Egl.EGL_PLATFORM_ANGLE_TYPE_ANGLE,                  Egl.EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,

                // Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
                // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
                Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,  Egl.EGL_TRUE,

                // Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
                // the IDXGIDevice3.Trim method on behalf of the application when it gets suspended.
                // Calling IDXGIDevice3.Trim when an application is suspended is a Windows Store application certification requirement.
                Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.EGL_TRUE,
                Egl.EGL_NONE,
            };

            int[] fl9_3DisplayAttributes =
            {
                // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
                // These attributes are used if the call to eglInitialize fails with the default display attributes.
                Egl.EGL_PLATFORM_ANGLE_TYPE_ANGLE,                  Egl.EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
                Egl.EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,                                           9,
                Egl.EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,                                           3,
                Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,  Egl.EGL_TRUE,
                Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.EGL_TRUE,
                Egl.EGL_NONE,
            };

            int[] warpDisplayAttributes =
            {
                // These attributes can be used to request D3D11 WARP.
                // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
                Egl.EGL_PLATFORM_ANGLE_TYPE_ANGLE,                  Egl.EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
                Egl.EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,           Egl.EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
                Egl.EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER,  Egl.EGL_TRUE,
                Egl.EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.EGL_TRUE,
                Egl.EGL_NONE,
            };

            //
            // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying
            // parameters passed to eglGetPlatformDisplayEXT:
            // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+.
            // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again
            //    using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3.
            // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again
            //    using "warpDisplayAttributes".  This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer.
            //

            // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
            var display = Egl.eglGetPlatformDisplayEXT(Egl.EGL_PLATFORM_ANGLE_ANGLE, Egl.EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);

            if (display == Egl.EGL_NO_DISPLAY)
            {
                throw new Exception("Failed to get EGL display (D3D11 10.0+).");
            }

            int major, minor;

            if (Egl.eglInitialize(display, out major, out minor) == Egl.EGL_FALSE)
            {
                // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
                display = Egl.eglGetPlatformDisplayEXT(Egl.EGL_PLATFORM_ANGLE_ANGLE, Egl.EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
                if (display == Egl.EGL_NO_DISPLAY)
                {
                    throw new Exception("Failed to get EGL display (D3D11 9.3).");
                }

                if (Egl.eglInitialize(display, out major, out minor) == Egl.EGL_FALSE)
                {
                    // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
                    display = Egl.eglGetPlatformDisplayEXT(Egl.EGL_PLATFORM_ANGLE_ANGLE, Egl.EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
                    if (display == Egl.EGL_NO_DISPLAY)
                    {
                        throw new Exception("Failed to get EGL display (D3D11 11.0 WARP)");
                    }

                    if (Egl.eglInitialize(display, out major, out minor) == Egl.EGL_FALSE)
                    {
                        // If all of the calls to eglInitialize returned Egl.EGL_FALSE then an error has occurred.
                        throw new Exception("Failed to initialize EGL");
                    }
                }
            }

            Egl.eglBindAPI(Egl.EGL_OPENGL_ES_API);
            if (Egl.eglGetError() != Egl.EGL_SUCCESS)
            {
                throw new Exception("Failed to bind API");
            }

            return(display);
        }
Beispiel #3
0
        static SurfaceFormat GetSurfaceFormat(IntPtr display, GraphicsMode mode)
        {
            // Use EGL 1.4 EGL_NATIVE_VISUAL_ID to retrieve
            // the corresponding surface format. If that fails
            // fall back to a manual algorithm.
            int format;

            Egl.GetConfigAttrib(display, mode.Index.Value,
                                Egl.NATIVE_VISUAL_ID, out format);
            if ((SurfaceFormat)format != 0)
            {
                return((SurfaceFormat)format);
            }

            Debug.Print("[KMS] Failed to retrieve EGL visual from GBM surface. Error: {0}",
                        Egl.GetError());
            Debug.Print("[KMS] Falling back to hardcoded formats.");

            int r = mode.ColorFormat.Red;
            int g = mode.ColorFormat.Green;
            int b = mode.ColorFormat.Blue;
            int a = mode.ColorFormat.Alpha;

            if (mode.ColorFormat.IsIndexed)
            {
                return(SurfaceFormat.C8);
            }
            if (r == 3 && g == 3 && b == 2 && a == 0)
            {
                return(SurfaceFormat.RGB332);
            }
            if (r == 5 && g == 6 && b == 5 && a == 0)
            {
                return(SurfaceFormat.RGB565);
            }
            if (r == 5 && g == 6 && b == 5 && a == 0)
            {
                return(SurfaceFormat.RGB565);
            }
            if (r == 8 && g == 8 && b == 8 && a == 0)
            {
                return(SurfaceFormat.RGB888);
            }
            if (r == 5 && g == 5 && b == 5 && a == 1)
            {
                return(SurfaceFormat.RGBA5551);
            }
            if (r == 10 && g == 10 && b == 10 && a == 2)
            {
                return(SurfaceFormat.RGBA1010102);
            }
            if (r == 4 && g == 4 && b == 4 && a == 4)
            {
                return(SurfaceFormat.RGBA4444);
            }
            if (r == 8 && g == 8 && b == 8 && a == 8)
            {
                return(SurfaceFormat.RGBA8888);
            }

            return(SurfaceFormat.RGBA8888);
        }
Beispiel #4
0
        //~CanvasRenderingContextHolographicSpace()
        //{
        //    deviceContext.MakeCurrent(IntPtr.Zero);
        //    deviceContext.DeleteContext(context);
        //}

        private IntPtr CreateEglContext(HolographicSpace holographicSpace, SpatialStationaryFrameOfReference stationaryReferenceFrame)
        {
            IntPtr context;

            int[] configAttribs = new int[]
            {
                Egl.RED_SIZE, 8,
                Egl.GREEN_SIZE, 8,
                Egl.BLUE_SIZE, 8,
                Egl.ALPHA_SIZE, 8,
                Egl.DEPTH_SIZE, 8,
                Egl.STENCIL_SIZE, 8,
                Egl.NONE
            };

            int[] contextAttribs = new int[]
            {
                Egl.CONTEXT_CLIENT_VERSION, 2,
                Egl.NONE
            };

            int[] surfaceAttribs = new int[] {
                EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, Egl.TRUE,
                Egl.NONE
            };

            int[] defaultDisplayAttribs = new int[]
            {
                EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
                EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.TRUE,
                EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.TRUE,
                Egl.NONE
            };

            int[] fl9_3DisplayAttributes = new int[]
            {
                // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
                // These attributes are used if the call to eglInitialize fails with the default display attributes.
                EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
                EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
                EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
                EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.TRUE,
                EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.TRUE,
                Egl.NONE
            };

            int[] warpDisplayAttributes = new int[]
            {
                // These attributes can be used to request D3D11 WARP.
                // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
                EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
                EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
                EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, Egl.TRUE,
                EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, Egl.TRUE,
                Egl.NONE
            };

            int[]    configCount = new int[1];
            IntPtr[] configs     = new IntPtr[8];

            if (Egl.BindAPI(Egl.OPENGL_ES_API) == false)
            {
                throw new InvalidOperationException("No OpenGL ES API");
            }

            if ((display = Egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, defaultDisplayAttribs)) == IntPtr.Zero)
            {
                throw new InvalidOperationException("Unable to get EGL display");
            }

            if (!Egl.Initialize(display, null, null))
            {
                if ((display = Egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, fl9_3DisplayAttributes)) == IntPtr.Zero)
                {
                    throw new InvalidOperationException("Unable to get EGL display");
                }

                if (!Egl.Initialize(display, null, null))
                {
                    if ((display = Egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, warpDisplayAttributes)) == IntPtr.Zero)
                    {
                        throw new InvalidOperationException("Unable to get EGL display");
                    }

                    if (!Egl.Initialize(display, null, null))
                    {
                        throw new InvalidOperationException("Unable to initialize EGL");
                    }
                }
            }

            if (!Egl.ChooseConfig(display, configAttribs, configs, 1, configCount))
            {
                throw new InvalidOperationException("Unable to choose configuration");
            }

            holographicSpaceHandle = GCHandle.Alloc(holographicSpace);
            IntPtr holographicSpacePointer = Marshal.GetIUnknownForObject(holographicSpace);

            //PropertySet surfaceCreationProperties = new PropertySet
            //{
            //    { "EGLNativeWindowTypeProperty", (IntPtr)holographicSpaceHandle }
            //};

            PropertySet surfaceCreationProperties = new PropertySet();

            surfaceCreationProperties.Add("EGLNativeWindowTypeProperty", holographicSpacePointer);

            //if (stationaryReferenceFrame != null)
            //{
            //    stationaryReferenceFrameHandle = GCHandle.Alloc(stationaryReferenceFrame);
            //    surfaceCreationProperties.Add("EGLBaseCoordinateSystemProperty", (IntPtr)stationaryReferenceFrameHandle);
            //}

            GCHandle surfaceCreationPropertiesHandle = GCHandle.Alloc(surfaceCreationProperties);

            IntPtr surfaceCreationPropertiesPointer = Marshal.GetIUnknownForObject(surfaceCreationProperties);

            if ((surface = Egl.CreateWindowSurface(display, configs[0], surfaceCreationPropertiesPointer, surfaceAttribs)) == IntPtr.Zero)
            {
                throw new InvalidOperationException("Unable to create EGL fullscreen surface");
            }

            if ((context = Egl.CreateContext(display, configs[0], IntPtr.Zero, contextAttribs)) == IntPtr.Zero)
            {
                throw new InvalidOperationException("Unable to create context");
            }

            return(context);
        }
Beispiel #5
0
 static void GetCurrentContext(int eventId)
 {
     currentContext = Egl.getCurrentContext();
 }
Beispiel #6
0
 public override void SwapBuffers()
 {
     Egl.SwapBuffers(_display, _surface);
 }
Beispiel #7
0
 static void GetCurrentContext(int eventId)
 {
     currentContext       = Egl.getCurrentContext();
     isContextInitialized = true;
 }
Beispiel #8
0
 public override void MakeCurrent()
 {
     Egl.MakeCurrent(_display, _surface, _surface, _context);
 }
Beispiel #9
0
 protected override void SetSwapIntervalPlatform(int interval)
 {
     Egl.SwapInterval(_display, interval);
 }
Beispiel #10
0
        public void Init(IntPtr nativeDeviceHandle, IntPtr nativeWindowHandle, PlatformBase platform)
        {
            _platform = platform;
            _eglLib   = platform.LoadLibrary("libEGL");
            if (_eglLib == IntPtr.Zero)
            {
                Engine.Log.Error("Couldn't load EGL.", MessageSource.Egl);
                return;
            }

            IntPtr gles = platform.LoadLibrary("libGLESv2");

            if (gles == IntPtr.Zero)
            {
                Engine.Log.Error("Couldn't load GLES.", MessageSource.Egl);
                return;
            }

            string extensions = Egl.QueryString(IntPtr.Zero, Egl.Query.EGL_EXTENSIONS);

            Egl.Error err = Egl.GetError();
            if (extensions == null || err != Egl.Error.Success)
            {
                Engine.Log.Error($"Couldn't load extensions. {err}", MessageSource.Egl);
                extensions = "";
            }

            _display = Egl.GetDisplay(nativeDeviceHandle);
            if (_display == IntPtr.Zero)
            {
                Engine.Log.Error($"Couldn't initialize display. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            var majorVersion = 3;
            int majorVer     = majorVersion;
            var minorVer     = 0;

            if (RenderDoc.Loaded)
            {
                minorVer = 1;
            }
            if (!Egl.Init(_display, ref majorVer, ref minorVer))
            {
                Engine.Log.Error($"Couldn't initialize Egl. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            // Pick config
            var totalConfigs = 0;

            Egl.GetConfigs(_display, null, 0, ref totalConfigs);
            if (totalConfigs == 0)
            {
                Engine.Log.Error($"No configs for current display. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            var configs = new IntPtr[totalConfigs];

            Egl.GetConfigs(_display, configs, totalConfigs, ref totalConfigs);
            if (totalConfigs == 0)
            {
                Engine.Log.Error($"No configs for current display. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            int configHandle = SupportedPixelFormat(configs);

            if (configHandle == 0)
            {
                Engine.Log.Error("No valid config found.", MessageSource.Egl);
                return;
            }

            IntPtr config = configs[configHandle - 1];

            if (!Egl.BindAPI(Egl.API.EGL_OPENGL_ES_API))
            {
                Engine.Log.Error($"Couldn't bind EGL API. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            int[] attributes =
            {
                (int)Egl.ContextAttribute.EGL_CONTEXT_CLIENT_VERSION,
                majorVersion,
                0x3038 // EGL_NONE
            };

            _context = Egl.CreateContext(_display, config, IntPtr.Zero, attributes);
            if (_context == IntPtr.Zero)
            {
                Engine.Log.Error($"Context creation failed. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            _surface = Egl.CreateWindowSurface(_display, config, nativeWindowHandle, null);
            if (_surface == IntPtr.Zero)
            {
                Engine.Log.Error($"Surface creation failed. {Egl.GetError()}", MessageSource.Egl);
                return;
            }

            Valid = true;
        }
Beispiel #11
0
        /// <summary>
        /// Finds the index of the supported pixel format closest to the requested pixel format.
        /// </summary>
        /// <returns>The index of the pixel format to use.</returns>
        private int SupportedPixelFormat(IntPtr[] configs)
        {
            var usableConfigs  = new List <FramebufferConfig>();
            var attributeValue = 0;

            for (var i = 0; i < configs.Length; i++)
            {
                IntPtr currentConfig = configs[i];

                // We only want RGB buffers.
                if (!Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_COLOR_BUFFER_TYPE, ref attributeValue))
                {
                    continue;
                }
                if (attributeValue != (int)Egl.ConfigValue.EGL_RGB_BUFFER)
                {
                    continue;
                }

                // We only want window type configs.
                // EGL_WINDOW_BIT 0x0004
                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_SURFACE_TYPE, ref attributeValue);
                if ((attributeValue & 0x0004) == 0)
                {
                    continue;
                }

                // We want configs that support ES2 (We actually want ES3, but there's no such bit)
                // EGL_OPENGL_ES2_BIT 0x0004
                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_RENDERABLE_TYPE, ref attributeValue);
                if ((attributeValue & 0x0004) == 0)
                {
                    continue;
                }

                var fbConfig = new FramebufferConfig();

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_RED_SIZE, ref attributeValue);
                fbConfig.RedBits = attributeValue;

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_GREEN_SIZE, ref attributeValue);
                fbConfig.GreenBits = attributeValue;

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_BLUE_SIZE, ref attributeValue);
                fbConfig.BlueBits = attributeValue;

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_ALPHA_SIZE, ref attributeValue);
                fbConfig.AlphaBits = attributeValue;

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_DEPTH_SIZE, ref attributeValue);
                fbConfig.DepthBits = attributeValue;

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_STENCIL_SIZE, ref attributeValue);
                fbConfig.StencilBits = attributeValue;

                Egl.GetConfigAttribute(_display, currentConfig, Egl.ConfigAttribute.EGL_SAMPLES, ref attributeValue);
                fbConfig.Samples      = attributeValue;
                fbConfig.Doublebuffer = true;

                fbConfig.Handle = i + 1;
                usableConfigs.Add(fbConfig);
            }

            if (usableConfigs.Count == 0)
            {
                Engine.Log.Error("The driver doesn't seem to support OpenGL.", MessageSource.WGallium);
                return(0);
            }

            FramebufferConfig closestConfig = ChoosePixelFormat(usableConfigs);

            if (closestConfig != null)
            {
                return(closestConfig.Handle);
            }

            Engine.Log.Error("Couldn't find suitable pixel format.", MessageSource.WGallium);
            return(0);
        }
Beispiel #12
0
 private static void GetCurrentContext(int eventId)
 {
     _CurrentContext       = Egl.GetCurrentContext();
     _IsContextInitialized = true;
 }