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