Skip to content

Commit

Permalink
Win32+Angle: reuse the first created D3D11 display
Browse files Browse the repository at this point in the history
  • Loading branch information
MrJul committed Sep 2, 2023
1 parent ee757f8 commit aee4078
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 148 deletions.
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

0 comments on commit aee4078

Please sign in to comment.