diff --git a/src/Avalonia.OpenGL/AngleOptions.cs b/src/Avalonia.OpenGL/AngleOptions.cs new file mode 100644 index 0000000000..4b9c04f4e6 --- /dev/null +++ b/src/Avalonia.OpenGL/AngleOptions.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace Avalonia.OpenGL +{ + public class AngleOptions + { + public enum PlatformApi + { + DirectX9, + DirectX11 + } + + public List AllowedPlatformApis = new List + { + PlatformApi.DirectX9 + }; + } +} diff --git a/src/Avalonia.OpenGL/EglDisplay.cs b/src/Avalonia.OpenGL/EglDisplay.cs index ec445a4605..b2b5a1a646 100644 --- a/src/Avalonia.OpenGL/EglDisplay.cs +++ b/src/Avalonia.OpenGL/EglDisplay.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using Avalonia.Platform.Interop; using static Avalonia.OpenGL.EglConsts; @@ -13,21 +14,42 @@ namespace Avalonia.OpenGL private readonly int[] _contextAttributes; public IntPtr Handle => _display; + private AngleOptions.PlatformApi? _angleApi; public EglDisplay(EglInterface egl) { _egl = egl; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _egl.GetPlatformDisplayEXT != null) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - foreach (var dapi in new[] {EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE}) + if (_egl.GetPlatformDisplayEXT == null) + throw new OpenGlException("eglGetPlatformDisplayEXT is not supported by libegl.dll"); + + var allowedApis = AvaloniaLocator.Current.GetService()?.AllowedPlatformApis + ?? new List {AngleOptions.PlatformApi.DirectX9}; + + foreach (var platformApi in allowedApis) { + int dapi; + if (platformApi == AngleOptions.PlatformApi.DirectX9) + dapi = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE; + else if (platformApi == AngleOptions.PlatformApi.DirectX11) + dapi = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE; + else + continue; + _display = _egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, new[] { EGL_PLATFORM_ANGLE_TYPE_ANGLE, dapi, EGL_NONE }); - if(_display != IntPtr.Zero) + if (_display != IntPtr.Zero) + { + _angleApi = platformApi; break; + } } + + if (_display == IntPtr.Zero) + throw new OpenGlException("Unable to create ANGLE display"); } if (_display == IntPtr.Zero) @@ -64,29 +86,35 @@ namespace Avalonia.OpenGL if (!_egl.BindApi(cfg.Api)) continue; - var attribs = new[] + foreach(var stencilSize in new[]{8, 1, 0}) + foreach (var depthSize in new []{8, 1, 0}) { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, cfg.RenderableTypeBit, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_STENCIL_SIZE, 8, - EGL_DEPTH_SIZE, 8, - EGL_NONE - }; - if (!_egl.ChooseConfig(_display, attribs, out _config, 1, out int numConfigs)) - continue; - if (numConfigs == 0) - continue; - _contextAttributes = cfg.Attributes; - Type = cfg.Type; + var attribs = new[] + { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + + EGL_RENDERABLE_TYPE, cfg.RenderableTypeBit, + + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_STENCIL_SIZE, stencilSize, + EGL_DEPTH_SIZE, depthSize, + EGL_NONE + }; + if (!_egl.ChooseConfig(_display, attribs, out _config, 1, out int numConfigs)) + continue; + if (numConfigs == 0) + continue; + _contextAttributes = cfg.Attributes; + Type = cfg.Type; + } } if (_contextAttributes == null) throw new OpenGlException("No suitable EGL config was found"); - + GlInterface = GlInterface.FromNativeUtf8GetProcAddress(b => _egl.GetProcAddress(b)); } diff --git a/src/Avalonia.OpenGL/EglInterface.cs b/src/Avalonia.OpenGL/EglInterface.cs index 2838e41461..0e4b012dbe 100644 --- a/src/Avalonia.OpenGL/EglInterface.cs +++ b/src/Avalonia.OpenGL/EglInterface.cs @@ -102,6 +102,19 @@ namespace Avalonia.OpenGL public delegate bool EglWaitNative(); [GlEntryPoint("eglWaitNative")] public EglWaitGL WaitNative { get; } + + public delegate IntPtr EglQueryString(IntPtr display, int i); + + [GlEntryPoint("eglQueryString")] + public EglQueryString QueryStringNative { get; } + + public string QueryString(IntPtr display, int i) + { + var rv = QueryStringNative(display, i); + if (rv == IntPtr.Zero) + return null; + return Marshal.PtrToStringAnsi(rv); + } // ReSharper restore UnassignedGetOnlyAutoProperty }