Document and test macOS Metal support

This commit is contained in:
geruipu committed 2026-09-08 10:46:32 +08:00
1 parent 572d14040d
commit 8371cd3a44
6 files changed
+214 -86

No files matched your search

+23 -1
View File
@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
namespace AvaloniaStaticLinkSmoke;
@@ -15,7 +16,28 @@ public sealed partial class App : Application
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
var renderer = Environment.GetEnvironmentVariable("STATICLINK_MAC_RENDERER") ?? "opengl";
var autoClose = Environment.GetEnvironmentVariable("STATICLINK_SMOKE_AUTOCLOSE") == "1";
desktop.MainWindow = new MainWindow(autoClose ? CompleteSmoke : null);
void CompleteSmoke(string backend)
{
Dispatcher.UIThread.Post(() =>
{
if (!renderer.Equals("metal", StringComparison.OrdinalIgnoreCase) ||
backend.Equals("Metal", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"STATICLINK_SMOKE_READY={renderer}");
}
else
{
Console.Error.WriteLine($"Expected the Metal renderer, but the active Skia backend was {backend}.");
Environment.ExitCode = 1;
}
desktop.MainWindow?.Close();
});
}
}
base.OnFrameworkInitializationCompleted();
@@ -1,11 +1,60 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia;
namespace AvaloniaStaticLinkSmoke;
public sealed partial class MainWindow : Window
{
public MainWindow()
private readonly Action<string>? _renderResult;
private int _renderResultReported;
public MainWindow() : this(null)
{
}
public MainWindow(Action<string>? renderResult)
{
_renderResult = renderResult;
InitializeComponent();
}
public override void Render(DrawingContext context)
{
base.Render(context);
if (_renderResult is not null)
{
context.Custom(new MetalBackendProbe(new Rect(Bounds.Size), ReportMetalResult));
}
}
private void ReportMetalResult(string backend)
{
if (Interlocked.Exchange(ref _renderResultReported, 1) == 0)
{
_renderResult?.Invoke(backend);
}
}
private sealed class MetalBackendProbe(Rect bounds, Action<string> report) : ICustomDrawOperation
{
public Rect Bounds { get; } = bounds;
public void Dispose()
{
}
public bool Equals(ICustomDrawOperation? other) => false;
public bool HitTest(Point point) => false;
public void Render(ImmediateDrawingContext context)
{
var feature = context.TryGetFeature(typeof(ISkiaSharpApiLeaseFeature)) as ISkiaSharpApiLeaseFeature;
using var lease = feature?.Lease();
report(lease?.GrContext?.Backend.ToString() ?? "Software");
}
}
}
+9 -7
View File
@@ -39,14 +39,16 @@ internal static class Program
if (OperatingSystem.IsMacOS())
{
builder = builder.With(new AvaloniaNativePlatformOptions
var renderer = Environment.GetEnvironmentVariable("STATICLINK_MAC_RENDERER");
if (!string.Equals(renderer, "default", StringComparison.OrdinalIgnoreCase))
{
RenderingMode =
[
AvaloniaNativeRenderingMode.OpenGl,
AvaloniaNativeRenderingMode.Software
]
});
builder = builder.With(new AvaloniaNativePlatformOptions
{
RenderingMode = string.Equals(renderer, "metal", StringComparison.OrdinalIgnoreCase)
? [AvaloniaNativeRenderingMode.Metal]
: [AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software]
});
}
}
return builder;