committed by
GitHub
6 changed files with 196 additions and 148 deletions
@ -1,143 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Diagnostics.CodeAnalysis; |
|
||||
using System.Linq; |
|
||||
using Avalonia.Logging; |
|
||||
using Avalonia.OpenGL; |
|
||||
using Avalonia.OpenGL.Angle; |
|
||||
using Avalonia.OpenGL.Egl; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Win32.OpenGl.Angle; |
|
||||
|
|
||||
internal class AngleWin32PlatformGraphics : IPlatformGraphics, IPlatformGraphicsOpenGlContextFactory |
|
||||
{ |
|
||||
private readonly Win32AngleEglInterface _egl; |
|
||||
private readonly AngleWin32EglDisplay? _sharedDisplay; |
|
||||
private EglContext? _sharedContext; |
|
||||
|
|
||||
[MemberNotNullWhen(true, nameof(_sharedDisplay))] |
|
||||
public bool UsesSharedContext => _sharedDisplay is not null; |
|
||||
|
|
||||
public AngleOptions.PlatformApi PlatformApi { get; } |
|
||||
|
|
||||
public IPlatformGraphicsContext CreateContext() |
|
||||
{ |
|
||||
if (UsesSharedContext) |
|
||||
throw new InvalidOperationException(); |
|
||||
|
|
||||
var display = AngleWin32EglDisplay.CreateD3D11Display(_egl); |
|
||||
var success = false; |
|
||||
try |
|
||||
{ |
|
||||
var rv = display.CreateContext(new EglContextOptions |
|
||||
{ |
|
||||
DisposeCallback = display.Dispose, |
|
||||
ExtraFeatures = new Dictionary<Type, Func<EglContext, object>> |
|
||||
{ |
|
||||
[typeof(IGlPlatformSurfaceRenderTargetFactory)] = _ => new AngleD3DTextureFeature(), |
|
||||
[typeof(IGlContextExternalObjectsFeature)] = context => new AngleExternalObjectsFeature(context) |
|
||||
} |
|
||||
}); |
|
||||
success = true; |
|
||||
return rv; |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
if (!success) |
|
||||
display.Dispose(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public IPlatformGraphicsContext GetSharedContext() |
|
||||
{ |
|
||||
if (!UsesSharedContext) |
|
||||
throw new InvalidOperationException(); |
|
||||
if (_sharedContext == null || _sharedContext.IsLost) |
|
||||
{ |
|
||||
_sharedContext?.Dispose(); |
|
||||
_sharedContext = null; |
|
||||
_sharedContext = _sharedDisplay.CreateContext(new EglContextOptions()); |
|
||||
} |
|
||||
|
|
||||
return _sharedContext; |
|
||||
} |
|
||||
|
|
||||
public AngleWin32PlatformGraphics(Win32AngleEglInterface egl, AngleWin32EglDisplay display) |
|
||||
: this(egl, display.PlatformApi) |
|
||||
{ |
|
||||
_sharedDisplay = display; |
|
||||
} |
|
||||
|
|
||||
public AngleWin32PlatformGraphics(Win32AngleEglInterface egl, AngleOptions.PlatformApi api) |
|
||||
{ |
|
||||
_egl = egl; |
|
||||
PlatformApi = api; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
public static AngleWin32PlatformGraphics? TryCreate(AngleOptions? options) |
|
||||
{ |
|
||||
Win32AngleEglInterface egl; |
|
||||
try |
|
||||
{ |
|
||||
egl = new(); |
|
||||
} |
|
||||
catch (Exception e) |
|
||||
{ |
|
||||
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
|
||||
?.Log(null, "Unable to load ANGLE: {0}", e); |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
foreach (var api in (options?.AllowedPlatformApis ?? new [] |
|
||||
{ |
|
||||
AngleOptions.PlatformApi.DirectX11 |
|
||||
}).Distinct()) |
|
||||
if (api == AngleOptions.PlatformApi.DirectX11) |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
using var display = AngleWin32EglDisplay.CreateD3D11Display(egl); |
|
||||
using var ctx = display.CreateContext(new EglContextOptions()); |
|
||||
ctx.MakeCurrent().Dispose(); |
|
||||
} |
|
||||
catch (Exception e) |
|
||||
{ |
|
||||
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
|
||||
?.Log(null, "Unable to initialize ANGLE-based rendering with DirectX11 : {0}", e); |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
return new AngleWin32PlatformGraphics(egl, AngleOptions.PlatformApi.DirectX11); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
AngleWin32EglDisplay? sharedDisplay = null; |
|
||||
try |
|
||||
{ |
|
||||
sharedDisplay = AngleWin32EglDisplay.CreateD3D9Display(egl); |
|
||||
using (var ctx = sharedDisplay.CreateContext(new EglContextOptions())) |
|
||||
ctx.MakeCurrent().Dispose(); |
|
||||
|
|
||||
return new AngleWin32PlatformGraphics(egl, sharedDisplay); |
|
||||
} |
|
||||
catch (Exception e) |
|
||||
{ |
|
||||
sharedDisplay?.Dispose(); |
|
||||
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
|
||||
?.Log(null, "Unable to initialize ANGLE-based rendering with DirectX9 : {0}", e); |
|
||||
} |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public IGlContext CreateContext(IEnumerable<GlVersion>? versions) |
|
||||
{ |
|
||||
if (UsesSharedContext) |
|
||||
throw new InvalidOperationException(); |
|
||||
if (versions != null && versions.All(v => v.Type != GlProfileType.OpenGLES || v.Major != 3)) |
|
||||
throw new OpenGlException("Unable to create context with requested version"); |
|
||||
return (IGlContext)CreateContext(); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,48 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using Avalonia.Logging; |
||||
|
using Avalonia.OpenGL.Angle; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Win32.OpenGl.Angle; |
||||
|
|
||||
|
internal static class AngleWin32PlatformGraphicsFactory |
||||
|
{ |
||||
|
public static IPlatformGraphics? TryCreate(AngleOptions? options) |
||||
|
{ |
||||
|
Win32AngleEglInterface egl; |
||||
|
try |
||||
|
{ |
||||
|
egl = new(); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
||||
|
?.Log(null, "Unable to load ANGLE: {0}", e); |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var allowedPlatformApis = options?.AllowedPlatformApis ?? new[] { AngleOptions.PlatformApi.DirectX11 }; |
||||
|
|
||||
|
foreach (var api in allowedPlatformApis.Distinct()) |
||||
|
{ |
||||
|
switch (api) |
||||
|
{ |
||||
|
case AngleOptions.PlatformApi.DirectX11 |
||||
|
when D3D11AngleWin32PlatformGraphics.TryCreate(egl) is { } platformGraphics: |
||||
|
return platformGraphics; |
||||
|
|
||||
|
case AngleOptions.PlatformApi.DirectX9 |
||||
|
when D3D9AngleWin32PlatformGraphics.TryCreate(egl) is { } platformGraphics: |
||||
|
return platformGraphics; |
||||
|
|
||||
|
default: |
||||
|
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
||||
|
?.Log(null, "Unknown requested PlatformApi {0}", api); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,91 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using Avalonia.Logging; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.OpenGL.Angle; |
||||
|
using Avalonia.OpenGL.Egl; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Win32.OpenGl.Angle; |
||||
|
|
||||
|
internal sealed class D3D11AngleWin32PlatformGraphics : IPlatformGraphics, IPlatformGraphicsOpenGlContextFactory |
||||
|
{ |
||||
|
private readonly Win32AngleEglInterface _egl; |
||||
|
private AngleWin32EglDisplay? _initialDisplay; |
||||
|
|
||||
|
public D3D11AngleWin32PlatformGraphics(Win32AngleEglInterface egl, AngleWin32EglDisplay? initialDisplay) |
||||
|
{ |
||||
|
_egl = egl; |
||||
|
_initialDisplay = initialDisplay; |
||||
|
} |
||||
|
|
||||
|
public bool UsesSharedContext |
||||
|
=> false; |
||||
|
|
||||
|
public IPlatformGraphicsContext CreateContext() |
||||
|
{ |
||||
|
var display = Interlocked.Exchange(ref _initialDisplay, null); |
||||
|
if (display is { IsLost: true }) |
||||
|
display = null; |
||||
|
|
||||
|
display ??= AngleWin32EglDisplay.CreateD3D11Display(_egl); |
||||
|
return CreateContextForDisplay(display); |
||||
|
} |
||||
|
|
||||
|
private static EglContext CreateContextForDisplay(AngleWin32EglDisplay display) |
||||
|
{ |
||||
|
var success = false; |
||||
|
try |
||||
|
{ |
||||
|
var context = display.CreateContext(new EglContextOptions |
||||
|
{ |
||||
|
DisposeCallback = display.Dispose, |
||||
|
ExtraFeatures = new Dictionary<Type, Func<EglContext, object>> |
||||
|
{ |
||||
|
[typeof(IGlPlatformSurfaceRenderTargetFactory)] = _ => new AngleD3DTextureFeature(), |
||||
|
[typeof(IGlContextExternalObjectsFeature)] = context => new AngleExternalObjectsFeature(context) |
||||
|
} |
||||
|
}); |
||||
|
success = true; |
||||
|
return context; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
if (!success) |
||||
|
display.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IGlContext CreateContext(IEnumerable<GlVersion>? versions) |
||||
|
{ |
||||
|
if (versions is not null && versions.All(v => v.Type != GlProfileType.OpenGLES || v.Major != 3)) |
||||
|
throw new OpenGlException("Unable to create context with requested version"); |
||||
|
|
||||
|
return (IGlContext)CreateContext(); |
||||
|
} |
||||
|
|
||||
|
IPlatformGraphicsContext IPlatformGraphics.GetSharedContext() |
||||
|
=> throw new InvalidOperationException(); |
||||
|
|
||||
|
public static D3D11AngleWin32PlatformGraphics? TryCreate(Win32AngleEglInterface egl) |
||||
|
{ |
||||
|
AngleWin32EglDisplay? display = null; |
||||
|
try |
||||
|
{ |
||||
|
display = AngleWin32EglDisplay.CreateD3D11Display(egl); |
||||
|
using var ctx = display.CreateContext(new EglContextOptions()); |
||||
|
ctx.MakeCurrent().Dispose(); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
display?.Dispose(); |
||||
|
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
||||
|
?.Log(null, "Unable to initialize ANGLE-based rendering with DirectX11 : {0}", e); |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return new D3D11AngleWin32PlatformGraphics(egl, display); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Logging; |
||||
|
using Avalonia.OpenGL.Angle; |
||||
|
using Avalonia.OpenGL.Egl; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Win32.OpenGl.Angle; |
||||
|
|
||||
|
internal sealed class D3D9AngleWin32PlatformGraphics : IPlatformGraphics |
||||
|
{ |
||||
|
private readonly AngleWin32EglDisplay _sharedDisplay; |
||||
|
private EglContext? _sharedContext; |
||||
|
|
||||
|
public D3D9AngleWin32PlatformGraphics(AngleWin32EglDisplay sharedDisplay) |
||||
|
=> _sharedDisplay = sharedDisplay; |
||||
|
|
||||
|
public bool UsesSharedContext |
||||
|
=> true; |
||||
|
|
||||
|
public IPlatformGraphicsContext GetSharedContext() |
||||
|
{ |
||||
|
if (_sharedContext is { IsLost: true }) |
||||
|
{ |
||||
|
_sharedContext.Dispose(); |
||||
|
_sharedContext = null; |
||||
|
} |
||||
|
|
||||
|
return _sharedContext ??= _sharedDisplay.CreateContext(new EglContextOptions()); |
||||
|
} |
||||
|
|
||||
|
IPlatformGraphicsContext IPlatformGraphics.CreateContext() |
||||
|
=> throw new InvalidOperationException(); |
||||
|
|
||||
|
public static D3D9AngleWin32PlatformGraphics? TryCreate(Win32AngleEglInterface egl) |
||||
|
{ |
||||
|
AngleWin32EglDisplay? sharedDisplay = null; |
||||
|
try |
||||
|
{ |
||||
|
sharedDisplay = AngleWin32EglDisplay.CreateD3D9Display(egl); |
||||
|
using var ctx = sharedDisplay.CreateContext(new EglContextOptions()); |
||||
|
ctx.MakeCurrent().Dispose(); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
sharedDisplay?.Dispose(); |
||||
|
Logger.TryGet(LogEventLevel.Error, "OpenGL") |
||||
|
?.Log(null, "Unable to initialize ANGLE-based rendering with DirectX9 : {0}", e); |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return new D3D9AngleWin32PlatformGraphics(sharedDisplay); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue