Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Win32+Angle: reuse the first created D3D11 display #12574

Merged
merged 1 commit into from
Sep 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 0 additions & 143 deletions src/Windows/Avalonia.Win32/OpenGl/Angle/AngleWin32PlatformGraphics.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
4 changes: 2 additions & 2 deletions src/Windows/Avalonia.Win32/Win32GlManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ static class Win32GlManager

if (renderingMode == Win32RenderingMode.AngleEgl)
{
var egl = AngleWin32PlatformGraphics.TryCreate(AvaloniaLocator.Current.GetService<AngleOptions>() ?? new());
var egl = AngleWin32PlatformGraphicsFactory.TryCreate(AvaloniaLocator.Current.GetService<AngleOptions>() ?? new());

if (egl != null && egl.PlatformApi == AngleOptions.PlatformApi.DirectX11)
if (egl is D3D11AngleWin32PlatformGraphics)
{
TryRegisterComposition(opts);
return egl;
Expand Down
5 changes: 2 additions & 3 deletions src/Windows/Avalonia.Win32/WindowImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ public WindowImpl()

var compositionConnector = AvaloniaLocator.Current.GetService<WinUiCompositorConnection>();

var isUsingAngleDX11 = glPlatform is AngleWin32PlatformGraphics angle &&
angle.PlatformApi == AngleOptions.PlatformApi.DirectX11;
var isUsingAngleDX11 = glPlatform is D3D11AngleWin32PlatformGraphics;
_isUsingComposition = compositionConnector is { } && isUsingAngleDX11;

DxgiConnection? dxgiConnection = null;
Expand Down Expand Up @@ -172,7 +171,7 @@ public WindowImpl()
}
else
{
if (glPlatform is AngleWin32PlatformGraphics)
if (glPlatform is D3D11AngleWin32PlatformGraphics or D3D9AngleWin32PlatformGraphics)
_gl = new EglGlPlatformSurface(this);
else if (glPlatform is WglPlatformOpenGlInterface)
_gl = new WglGlPlatformSurface(this);
Expand Down