Browse Source

Restructure Win32PlatformOptions options

pull/11898/head
Max Katz 3 years ago
parent
commit
29d3c7670b
  1. 3
      samples/ControlCatalog.NetCore/Program.cs
  2. 37
      src/Windows/Avalonia.Win32/Win32GlManager.cs
  3. 74
      src/Windows/Avalonia.Win32/Win32Platform.cs
  4. 114
      src/Windows/Avalonia.Win32/Win32PlatformOptions.cs
  5. 2
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
  6. 1
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs
  7. 31
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositorConnection.cs

3
samples/ControlCatalog.NetCore/Program.cs

@ -110,8 +110,7 @@ namespace ControlCatalog.NetCore
{ {
builder.With(new Win32PlatformOptions() builder.With(new Win32PlatformOptions()
{ {
UseLowLatencyDxgiSwapChain = true, CompositionMode = Win32CompositionMode.LowLatencyDxgiSwapChain
UseWindowsUIComposition = false
}); });
return builder.StartWithClassicDesktopLifetime(args); return builder.StartWithClassicDesktopLifetime(args);
} }

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

@ -1,3 +1,4 @@
using System;
using Avalonia.OpenGL; using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Win32.DirectX; using Avalonia.Win32.DirectX;
@ -23,15 +24,19 @@ namespace Avalonia.Win32
private static IPlatformGraphics? InitializeCore() private static IPlatformGraphics? InitializeCore()
{ {
var opts = AvaloniaLocator.Current.GetService<Win32PlatformOptions>() ?? new Win32PlatformOptions(); var opts = AvaloniaLocator.Current.GetService<Win32PlatformOptions>() ?? new Win32PlatformOptions();
if (opts.UseWgl)
var winVersion = Win32Platform.WindowsVersion;
var renderingMode = opts.RenderingMode ??
(winVersion > PlatformConstants.Windows7 ? Win32RenderingMode.AngleEgl : Win32RenderingMode.Software);
if (renderingMode == Win32RenderingMode.Wgl)
{ {
var wgl = WglPlatformOpenGlInterface.TryCreate(); var wgl = WglPlatformOpenGlInterface.TryCreate();
return wgl; return wgl;
} }
if (opts.AllowEglInitialization ?? Win32Platform.WindowsVersion > PlatformConstants.Windows7) if (renderingMode == Win32RenderingMode.AngleEgl)
{ {
var egl = AngleWin32PlatformGraphics.TryCreate(AvaloniaLocator.Current.GetService<AngleOptions>() ?? var egl = AngleWin32PlatformGraphics.TryCreate(AvaloniaLocator.Current.GetService<AngleOptions>() ??
new()); new());
@ -40,14 +45,26 @@ namespace Avalonia.Win32
{ {
AvaloniaLocator.CurrentMutable.Bind<IPlatformGraphicsOpenGlContextFactory>() AvaloniaLocator.CurrentMutable.Bind<IPlatformGraphicsOpenGlContextFactory>()
.ToConstant(egl); .ToConstant(egl);
if (opts.UseWindowsUIComposition) var compositionMode = opts.CompositionMode ??
{ (WinUiCompositorConnection.IsSupported() ? Win32CompositionMode.WinUIComposition
WinUiCompositorConnection.TryCreateAndRegister(); //: DirectCompositionConnection.IsSupported() ? Win32CompositionMode.DirectComposition
} : Win32CompositionMode.RedirectionSurface);
else if (opts.UseLowLatencyDxgiSwapChain)
switch (compositionMode)
{ {
DxgiConnection.TryCreateAndRegister(); case Win32CompositionMode.WinUIComposition:
if (!WinUiCompositorConnection.TryCreateAndRegister())
{
//goto case Win32CompositionMode.DirectComposition;
}
break;
//case Win32CompositionMode.DirectComposition:
//DirectCompositionConnection.TryCreateAndRegister();
//break;
case Win32CompositionMode.LowLatencyDxgiSwapChain:
DxgiConnection.TryCreateAndRegister();
break;
} }
} }

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

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
@ -10,7 +9,6 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Platform; using Avalonia.Input.Platform;
using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition; using Avalonia.Rendering.Composition;
@ -31,78 +29,6 @@ namespace Avalonia
"Win32"); "Win32");
} }
} }
/// <summary>
/// Platform-specific options which apply to Windows.
/// </summary>
public class Win32PlatformOptions
{
/// <summary>
/// Enables ANGLE for Windows. For every Windows version that is above Windows 7, the default is true otherwise it's false.
/// </summary>
/// <remarks>
/// GPU rendering will not be enabled if this is set to false.
/// </remarks>
public bool? AllowEglInitialization { get; set; }
/// <summary>
/// Embeds popups to the window when set to true. The default value is false.
/// </summary>
public bool OverlayPopups { get; set; }
/// <summary>
/// Avalonia would try to use native Widows OpenGL when set to true. The default value is false.
/// </summary>
public bool UseWgl { get; set; }
public IList<GlVersion> WglProfiles { get; set; } = new List<GlVersion>
{
new GlVersion(GlProfileType.OpenGL, 4, 0),
new GlVersion(GlProfileType.OpenGL, 3, 2),
};
/// <summary>
/// Render Avalonia to a Texture inside the Windows.UI.Composition tree.
/// This setting is true by default.
/// </summary>
/// <remarks>
/// Supported on Windows 10 build 16299 and above. Ignored on other versions.
/// This is recommended if you need to use AcrylicBlur or acrylic in your applications.
/// </remarks>
public bool UseWindowsUIComposition { get; set; } = true;
/// <summary>
/// When <see cref="UseWindowsUIComposition"/> enabled, create rounded corner blur brushes
/// If set to null the brushes will be created using default settings (sharp corners)
/// This can be useful when you need a rounded-corner blurred Windows 10 app, or borderless Windows 11 app
/// </summary>
public float? CompositionBackdropCornerRadius { get; set; }
/// <summary>
/// When <see cref="UseLowLatencyDxgiSwapChain"/> is active, renders Avalonia through a low-latency Dxgi Swapchain.
/// 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 stylings / blurrings offered by <see cref="UseWindowsUIComposition"/><br/>
/// This is mutually exclusive with
/// <see cref="UseWindowsUIComposition"/> which if active will override this setting.
/// This setting is false by default.
/// </summary>
public bool UseLowLatencyDxgiSwapChain { get; set; }
/// <summary>
/// Render directly on the UI thread instead of using a dedicated render thread.
/// Only applicable if both <see cref="UseWindowsUIComposition"/> and <see cref="UseLowLatencyDxgiSwapChain"/>
/// are false.
/// This setting is only recommended for interop with systems that must render on the UI thread, such as WPF.
/// This setting is false by default.
/// </summary>
public bool ShouldRenderOnUIThread { get; set; }
/// <summary>
/// Provides a way to use a custom-implemented graphics context such as a custom ISkiaGpu
/// </summary>
public IPlatformGraphics? CustomPlatformGraphics { get; set; }
}
} }
namespace Avalonia.Win32 namespace Avalonia.Win32

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

@ -0,0 +1,114 @@
using System.Collections.Generic;
using Avalonia.OpenGL;
using Avalonia.Platform;
namespace Avalonia;
public enum Win32RenderingMode
{
/// <summary>
/// Avalonia is rendered into a framebuffer.
/// </summary>
Software = 1,
/// <summary>
/// Enables ANGLE EGL for Windows with GPU rendering.
/// </summary>
AngleEgl = 2,
/// <summary>
/// Avalonia would try to use native Widows OpenGL with GPU rendering.
/// </summary>
Wgl
}
public enum Win32CompositionMode
{
/// <summary>
/// Render Avalonia to a texture inside the Windows.UI.Composition tree.
/// </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.
/// </remarks>
WinUIComposition = 1,
// /// <summary>
// /// Render Avalonia to a texture inside the DirectComposition tree.
// /// </summary>
// /// <remarks>
// /// Supported on Windows 8 and above. Ignored on other versions.
// /// </remarks>
// DirectComposition = 2,
/// <summary>
/// When <see cref="LowLatencyDxgiSwapChain"/> is active, renders Avalonia through a low-latency Dxgi Swapchain.
/// 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>
LowLatencyDxgiSwapChain = 3,
/// <summary>
/// The window renders to a redirection surface.
/// </summary>
/// <remarks>
/// This option is kept only for compatibility with older systems. Some Avalonia features might not work.
/// </remarks>
RedirectionSurface,
}
/// <summary>
/// Platform-specific options which apply to Windows.
/// </summary>
public class Win32PlatformOptions
{
/// <summary>
/// Embeds popups to the window when set to true. The default value is false.
/// </summary>
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.
/// </summary>
public Win32RenderingMode? RenderingMode { get; set; }
/// <summary>
/// Avalonia window composition mode.
/// On Windows 8 and newer default value is <see cref="Win32CompositionMode.WinUIComposition"/>,
/// <see cref="Win32CompositionMode.RedirectionSurface"/> otherwise.
/// </summary>
public Win32CompositionMode? CompositionMode { get; set; }
/// <summary>
/// When <see cref="CompositionMode"/> is set to <see cref="Win32CompositionMode.WinUIComposition"/>, create rounded corner blur brushes
/// If set to null the brushes will be created using default settings (sharp corners)
/// This can be useful when you need a rounded-corner blurred Windows 10 app, or borderless Windows 11 app.
/// </summary>
public float? WinUICompositionBackdropCornerRadius { get; set; }
/// <summary>
/// Render directly on the UI thread instead of using a dedicated render thread.
/// Only applicable if <see cref="CompositionMode"/> is set to <see cref="Win32CompositionMode.None"/>.
/// This setting is only recommended for interop with systems that must render on the UI thread, such as WPF.
/// This setting is false by default.
/// </summary>
public bool ShouldRenderOnUIThread { get; set; }
/// <summary>
/// Windows OpenGL profiles used when <see cref="RenderingMode"/> is set to <see cref="Win32RenderingMode.Wgl"/>.
/// This setting is 4.0 and 3.2 by default.
/// </summary>
public IList<GlVersion> WglProfiles { get; set; } = new List<GlVersion>
{
new(GlProfileType.OpenGL, 4, 0), new(GlProfileType.OpenGL, 3, 2)
};
/// <summary>
/// Provides a way to use a custom-implemented graphics context such as a custom ISkiaGpu.
/// When this property set <see cref="RenderingMode"/> and <see cref="CompositionMode"/> are completely ignored.
/// </summary>
public IPlatformGraphics? CustomPlatformGraphics { get; set; }
}

2
src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs

@ -23,7 +23,7 @@ namespace Avalonia.Win32.WinRT.Composition
public IDirect3D11TextureRenderTarget CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice) public IDirect3D11TextureRenderTarget CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
{ {
var cornerRadius = AvaloniaLocator.Current.GetService<Win32PlatformOptions>() var cornerRadius = AvaloniaLocator.Current.GetService<Win32PlatformOptions>()
?.CompositionBackdropCornerRadius; ?.WinUICompositionBackdropCornerRadius;
_window ??= new WinUiCompositedWindow(_info, _shared, cornerRadius); _window ??= new WinUiCompositedWindow(_info, _shared, cornerRadius);
_window.SetBlur(_blurEffect); _window.SetBlur(_blurEffect);

1
src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs

@ -12,6 +12,7 @@ internal class WinUiCompositionShared : IDisposable
public ICompositionBrush? MicaBrush { get; } public ICompositionBrush? MicaBrush { get; }
public object SyncRoot { get; } = new(); public object SyncRoot { get; } = new();
public static readonly Version MinWinCompositionVersion = new(10, 0, 17134);
public static readonly Version MinAcrylicVersion = new(10, 0, 15063); public static readonly Version MinAcrylicVersion = new(10, 0, 15063);
public static readonly Version MinHostBackdropVersion = new(10, 0, 22000); public static readonly Version MinHostBackdropVersion = new(10, 0, 22000);

31
src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositorConnection.cs

@ -112,35 +112,36 @@ internal class WinUiCompositorConnection : IRenderTimer
} }
} }
public static void TryCreateAndRegister() public static bool IsSupported()
{ {
const int majorRequired = 10; return Win32Platform.WindowsVersion >= WinUiCompositionShared.MinWinCompositionVersion;
const int buildRequired = 17134; }
var majorInstalled = Win32Platform.WindowsVersion.Major; public static bool TryCreateAndRegister()
var buildInstalled = Win32Platform.WindowsVersion.Build; {
if (Win32Platform.WindowsVersion >= WinUiCompositionShared.MinWinCompositionVersion)
if (majorInstalled >= majorRequired &&
buildInstalled >= buildRequired)
{ {
try try
{ {
TryCreateAndRegisterCore(); TryCreateAndRegisterCore();
return; return true;
} }
catch (Exception e) catch (Exception e)
{ {
Logger.TryGet(LogEventLevel.Error, "WinUIComposition") Logger.TryGet(LogEventLevel.Error, "WinUIComposition")
?.Log(null, "Unable to initialize WinUI compositor: {0}", e); ?.Log(null, "Unable to initialize WinUI compositor: {0}", e);
} }
} }
else
{
var osVersionNotice =
$"Windows {WinUiCompositionShared.MinWinCompositionVersion} is required. Your machine has Windows {Win32Platform.WindowsVersion} installed.";
var osVersionNotice = Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null,
$"Windows {majorRequired} Build {buildRequired} is required. Your machine has Windows {majorInstalled} Build {buildInstalled} installed."; $"Unable to initialize WinUI compositor: {osVersionNotice}");
}
Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null, return false;
$"Unable to initialize WinUI compositor: {osVersionNotice}");
} }
public WinUiCompositedWindowSurface CreateSurface(EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info) => new(_shared, info); public WinUiCompositedWindowSurface CreateSurface(EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info) => new(_shared, info);

Loading…
Cancel
Save