Browse Source

Make RenderingMode and CompositionMode lists with fallbacks

pull/11898/head
Max Katz 3 years ago
parent
commit
a390f9f50c
  1. 2
      samples/ControlCatalog.NetCore/Program.cs
  2. 4
      src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs
  3. 112
      src/Windows/Avalonia.Win32/Win32GlManager.cs
  4. 4
      src/Windows/Avalonia.Win32/Win32Platform.cs
  5. 43
      src/Windows/Avalonia.Win32/Win32PlatformOptions.cs

2
samples/ControlCatalog.NetCore/Program.cs

@ -110,7 +110,7 @@ namespace ControlCatalog.NetCore
{
builder.With(new Win32PlatformOptions()
{
CompositionMode = Win32CompositionMode.LowLatencyDxgiSwapChain
CompositionMode = new [] { Win32CompositionMode.LowLatencyDxgiSwapChain }
});
return builder.StartWithClassicDesktopLifetime(args);
}

4
src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs

@ -28,16 +28,18 @@ namespace Avalonia.Win32.DirectX
_syncLock = syncLock;
}
public static void TryCreateAndRegister()
public static bool TryCreateAndRegister()
{
try
{
TryCreateAndRegisterCore();
return true;
}
catch (Exception ex)
{
Logger.TryGet(LogEventLevel.Error, LogArea)
?.Log(null, "Unable to establish Dxgi: {0}", ex);
return false;
}
}

112
src/Windows/Avalonia.Win32/Win32GlManager.cs

@ -1,4 +1,6 @@
using System;
using System.Diagnostics.Tracing;
using System.Linq;
using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Win32.DirectX;
@ -6,72 +8,88 @@ using Avalonia.Win32.OpenGl;
using Avalonia.Win32.OpenGl.Angle;
using Avalonia.Win32.WinRT.Composition;
namespace Avalonia.Win32
namespace Avalonia.Win32;
static class Win32GlManager
{
static class Win32GlManager
public static IPlatformGraphics? Initialize()
{
public static IPlatformGraphics? Initialize()
{
var gl = InitializeCore();
if (gl is not null)
{
AvaloniaLocator.CurrentMutable.Bind<IPlatformGraphics>().ToConstant(gl);
}
var gl = InitializeCore();
return gl;
if (gl is not null)
{
AvaloniaLocator.CurrentMutable.Bind<IPlatformGraphics>().ToConstant(gl);
}
return gl;
}
private static IPlatformGraphics? InitializeCore()
private static IPlatformGraphics? InitializeCore()
{
var opts = AvaloniaLocator.Current.GetService<Win32PlatformOptions>() ?? new Win32PlatformOptions();
if (opts.RenderingMode is null || !opts.RenderingMode.Any())
{
var opts = AvaloniaLocator.Current.GetService<Win32PlatformOptions>() ?? new Win32PlatformOptions();
throw new InvalidOperationException($"{nameof(Win32PlatformOptions)}.{nameof(Win32PlatformOptions.RenderingMode)} must not be empty or null");
}
var winVersion = Win32Platform.WindowsVersion;
var renderingMode = opts.RenderingMode ??
(winVersion > PlatformConstants.Windows7 ? Win32RenderingMode.AngleEgl : Win32RenderingMode.Software);
if (renderingMode == Win32RenderingMode.Wgl)
foreach (var renderingMode in opts.RenderingMode)
{
if (renderingMode == Win32RenderingMode.Software)
{
var wgl = WglPlatformOpenGlInterface.TryCreate();
return wgl;
return null;
}
if (renderingMode == Win32RenderingMode.AngleEgl)
{
var egl = AngleWin32PlatformGraphics.TryCreate(AvaloniaLocator.Current.GetService<AngleOptions>() ??
new());
var egl = AngleWin32PlatformGraphics.TryCreate(AvaloniaLocator.Current.GetService<AngleOptions>() ?? new());
if (egl != null && egl.PlatformApi == AngleOptions.PlatformApi.DirectX11)
{
AvaloniaLocator.CurrentMutable.Bind<IPlatformGraphicsOpenGlContextFactory>()
.ToConstant(egl);
var compositionMode = opts.CompositionMode ??
(WinUiCompositorConnection.IsSupported() ? Win32CompositionMode.WinUIComposition
//: DirectCompositionConnection.IsSupported() ? Win32CompositionMode.DirectComposition
: Win32CompositionMode.RedirectionSurface);
TryRegisterComposition(opts);
return egl;
}
}
switch (compositionMode)
{
case Win32CompositionMode.WinUIComposition:
if (!WinUiCompositorConnection.TryCreateAndRegister())
{
//goto case Win32CompositionMode.DirectComposition;
}
break;
//case Win32CompositionMode.DirectComposition:
//DirectCompositionConnection.TryCreateAndRegister();
//break;
case Win32CompositionMode.LowLatencyDxgiSwapChain:
DxgiConnection.TryCreateAndRegister();
break;
}
if (renderingMode == Win32RenderingMode.Wgl)
{
if (WglPlatformOpenGlInterface.TryCreate() is { } wgl)
{
return wgl;
}
}
}
throw new InvalidOperationException($"{nameof(Win32PlatformOptions)}.{nameof(Win32PlatformOptions.RenderingMode)} has a value of \"{string.Join(", ", opts.RenderingMode)}\", but no options were applied.");
}
private static void TryRegisterComposition(Win32PlatformOptions opts)
{
if (opts.CompositionMode is null || !opts.CompositionMode.Any())
{
throw new InvalidOperationException($"{nameof(Win32PlatformOptions)}.{nameof(Win32PlatformOptions.CompositionMode)} must not be empty or null");
}
return egl;
foreach (var compositionMode in opts.CompositionMode)
{
if (compositionMode == Win32CompositionMode.RedirectionSurface)
{
return;
}
return null;
if (compositionMode == Win32CompositionMode.WinUIComposition
&& WinUiCompositorConnection.IsSupported()
&& WinUiCompositorConnection.TryCreateAndRegister())
{
return;
}
if (compositionMode == Win32CompositionMode.LowLatencyDxgiSwapChain
&& DxgiConnection.TryCreateAndRegister())
{
return;
}
}
throw new InvalidOperationException($"{nameof(Win32PlatformOptions)}.{nameof(Win32PlatformOptions.CompositionMode)} has a value of \"{string.Join(", ", opts.CompositionMode)}\", but no options were applied.");
}
}

4
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -2,6 +2,7 @@ using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Avalonia.Reactive;
using System.Runtime.InteropServices;
using System.Threading;
@ -103,8 +104,7 @@ namespace Avalonia.Win32
IPlatformGraphics? platformGraphics;
if (options.CustomPlatformGraphics is not null)
{
if (options.CompositionMode.HasValue
&& options.CompositionMode != Win32CompositionMode.RedirectionSurface)
if (options.CompositionMode?.Contains(Win32CompositionMode.RedirectionSurface) == false)
{
throw new InvalidOperationException(
$"{nameof(Win32PlatformOptions)}.{nameof(Win32PlatformOptions.CustomPlatformGraphics)} is only " +

43
src/Windows/Avalonia.Win32/Win32PlatformOptions.cs

@ -29,7 +29,8 @@ public enum Win32CompositionMode
/// </summary>
/// <remarks>
/// Supported on Windows 10 build 17134 and above. Ignored on other versions.
/// This is recommended option, as it allows window acrylic effects and high refresh rate rendering.
/// This is recommended option, as it allows window acrylic effects and high refresh rate rendering.<br/>
/// Can only be applied with <see cref="Win32PlatformOptions.RenderingMode"/>=<see cref="Win32RenderingMode.AngleEgl"/>.
/// </remarks>
WinUIComposition = 1,
@ -37,16 +38,20 @@ public enum Win32CompositionMode
// /// Render Avalonia to a texture inside the DirectComposition tree.
// /// </summary>
// /// <remarks>
// /// Supported on Windows 8 and above. Ignored on other versions.
// /// Supported on Windows 8 and above. Ignored on other versions.<br/>
// /// Can only be applied with <see cref="Win32PlatformOptions.RenderingMode"/>=<see cref="Win32RenderingMode.AngleEgl"/>.
// /// </remarks>
// DirectComposition = 2,
/// <summary>
/// When <see cref="LowLatencyDxgiSwapChain"/> is active, renders Avalonia through a low-latency Dxgi Swapchain.
/// </summary>
/// <remarks>
/// Requires Feature Level 11_3 to be active, Windows 8.1+ Any Subversion.
/// This is only recommended if low input latency is desirable, and there is no need for the transparency
/// and styling / blurring offered by <see cref="WinUIComposition"/><br/>.
/// </summary>
/// and styling / blurring offered by <see cref="WinUIComposition"/>.<br/>
/// Can only be applied with <see cref="Win32PlatformOptions.RenderingMode"/>=<see cref="Win32RenderingMode.AngleEgl"/>.
/// </remarks>
LowLatencyDxgiSwapChain = 3,
/// <summary>
@ -69,18 +74,32 @@ public class Win32PlatformOptions
public bool OverlayPopups { get; set; }
/// <summary>
/// Avalonia window rendering mode.
/// On Windows 8 and newer default value is <see cref="Win32RenderingMode.AngleEgl"/>,
/// <see cref="Win32RenderingMode.Software"/> otherwise.
/// Gets or sets Avalonia rendering modes with fallbacks.
/// The first element in the array has the highest priority.
/// The default value is: <see cref="Win32RenderingMode.AngleEgl"/>, <see cref="Win32RenderingMode.Software"/>.
/// </summary>
public Win32RenderingMode? RenderingMode { get; set; }
/// <remarks>
/// If application should work on as wide range of devices as possible, at least add <see cref="Win32RenderingMode.Software"/> as a fallback value.
/// </remarks>
/// <exception cref="System.InvalidOperationException">Thrown if no values were matched.</exception>
public IReadOnlyList<Win32RenderingMode> RenderingMode { get; set; } = new[]
{
Win32RenderingMode.AngleEgl, Win32RenderingMode.Software
};
/// <summary>
/// Avalonia window composition mode.
/// On Windows 8 and newer default value is <see cref="Win32CompositionMode.WinUIComposition"/>,
/// <see cref="Win32CompositionMode.RedirectionSurface"/> otherwise.
/// Gets or sets Avalonia composition modes with fallbacks.
/// The first element in the array has the highest priority.
/// The default value is: <see cref="Win32CompositionMode.WinUIComposition"/>, <see cref="Win32CompositionMode.RedirectionSurface"/>.
/// </summary>
public Win32CompositionMode? CompositionMode { get; set; }
/// <remarks>
/// If application should work on as wide range of devices as possible, at least add <see cref="Win32CompositionMode.RedirectionSurface"/> as a fallback value.
/// </remarks>
/// <exception cref="System.InvalidOperationException">Thrown if no values were matched.</exception>
public IReadOnlyList<Win32CompositionMode> CompositionMode { get; set; } = new[]
{
Win32CompositionMode.WinUIComposition, Win32CompositionMode.RedirectionSurface
};
/// <summary>
/// When <see cref="CompositionMode"/> is set to <see cref="Win32CompositionMode.WinUIComposition"/>, create rounded corner blur brushes

Loading…
Cancel
Save