Browse Source

[12.0] Target SkiaSharp 3.0. Drop 2.88 support (#18981)

* Retarget to SkiaSharp 3.0

* Replace SKFilterQuality with SKSamplingOptions

* Replace obsolete GRBackendRenderTarget ctor

* Replace SkiaMetalApi reflection with stable APIs

* Use SKMatrix4x4 where it makes more sense perf wise

* Add CS0618 warning as error for Skia

* Fix ToSKSamplingOptions implementation

* Remove hacky compile time condition

* Update API compat

* Remove maccatalyst hack

---------

Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
pull/19209/head
Max Katz 7 months ago
committed by GitHub
parent
commit
b644cee98f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      api/Avalonia.Skia.nupkg.xml
  2. 7
      build/SkiaSharp.props
  3. 2
      src/Skia/Avalonia.Skia/Avalonia.Skia.csproj
  4. 13
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  5. 108
      src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalApi.cs
  6. 15
      src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs
  7. 4
      src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaExternalObjectsFeature.cs
  8. 2
      src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaRenderTarget.cs
  9. 3
      src/Skia/Avalonia.Skia/IDrawableBitmapImpl.cs
  10. 10
      src/Skia/Avalonia.Skia/ImmutableBitmap.cs
  11. 56
      src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs
  12. 7
      src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
  13. 6
      src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
  14. 12
      src/iOS/Avalonia.iOS/Metal/MetalPlatformGraphics.cs
  15. 6
      tests/Avalonia.RenderTests/TestBase.cs
  16. 5
      tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj

6
api/Avalonia.Skia.nupkg.xml

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.SkiaSharpExtensions.ToSKFilterQuality(Avalonia.Media.Imaging.BitmapInterpolationMode)</Target>
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left>
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuWithPlatformGraphicsContext.TryGetGrContext</Target>

7
build/SkiaSharp.props

@ -1,10 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Condition="'$(AvsIncludeSkiaSharp3)' != 'true'">
<PackageReference Include="SkiaSharp" Version="2.88.9" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="2.88.9" />
</ItemGroup>
<ItemGroup Condition="'$(AvsIncludeSkiaSharp3)' == 'true'">
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="3.119.0" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="3.119.0" />
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.0" />

2
src/Skia/Avalonia.Skia/Avalonia.Skia.csproj

@ -4,6 +4,8 @@
<IncludeLinuxSkia>true</IncludeLinuxSkia>
<IncludeWasmSkia>true</IncludeWasmSkia>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- No obsolete code usage -->
<WarningsAsErrors>$(WarningsAsErrors);CS0618</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Assets\NoiseAsset_256X256_PNG.png" />

13
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -246,12 +246,12 @@ namespace Avalonia.Skia
var d = destRect.ToSKRect();
var paint = SKPaintCache.Shared.Get();
var samplingOptions = RenderOptions.BitmapInterpolationMode.ToSKSamplingOptions();
paint.Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity));
paint.FilterQuality = RenderOptions.BitmapInterpolationMode.ToSKFilterQuality();
paint.BlendMode = RenderOptions.BitmapBlendingMode.ToSKBlendMode();
drawableImage.Draw(this, s, d, paint);
drawableImage.Draw(this, s, d, samplingOptions, paint);
SKPaintCache.Shared.ReturnReset(paint);
}
@ -844,7 +844,9 @@ namespace Avalonia.Skia
/// <inheritdoc />
public Matrix Transform
{
get { return _currentTransform ??= Canvas.TotalMatrix.ToAvaloniaMatrix(); }
// There is a Canvas.TotalMatrix (non 4x4 overload), but internally it still uses 4x4 matrix.
// We want to avoid SKMatrix4x4 -> SKMatrix -> Matrix conversion by directly going SKMatrix4x4 -> Matrix.
get { return _currentTransform ??= Canvas.TotalMatrix44.ToAvaloniaMatrix(); }
set
{
CheckLease();
@ -860,7 +862,9 @@ namespace Avalonia.Skia
transform *= _postTransform.Value;
}
Canvas.SetMatrix(transform.ToSKMatrix());
// Canvas.SetMatrix internally uses 4x4 matrix, even with SKMatrix(3x3) overload.
// We want to avoid Matrix -> SKMatrix -> SKMatrix4x4 conversion by directly going Matrix -> SKMatrix4x4.
Canvas.SetMatrix(transform.ToSKMatrix44());
}
}
@ -1257,7 +1261,6 @@ namespace Avalonia.Skia
using(var shader = tile.ToShader(tileX, tileY, shaderTransform.ToSKMatrix(),
new SKRect(0, 0, tile.CullRect.Width, tile.CullRect.Height)))
{
paintWrapper.Paint.FilterQuality = SKFilterQuality.None;
paintWrapper.Paint.Shader = shader;
}
}

108
src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalApi.cs

@ -1,108 +0,0 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Avalonia.Compatibility;
using Avalonia.Platform.Interop;
using SkiaSharp;
using BindingFlags = System.Reflection.BindingFlags;
namespace Avalonia.Skia.Metal;
internal unsafe class SkiaMetalApi
{
delegate* unmanaged[Stdcall] <IntPtr, IntPtr, IntPtr, IntPtr> _gr_direct_context_make_metal_with_options;
private delegate* unmanaged[Stdcall]<int, int, int, GRMtlTextureInfoNative*, IntPtr>
_gr_backendrendertarget_new_metal;
private readonly ConstructorInfo _contextCtor;
private readonly MethodInfo _contextOptionsToNative;
private readonly ConstructorInfo _renderTargetCtor;
[DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(GRContext))]
[DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(GRBackendRenderTarget))]
[DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicMethods, typeof(GRContextOptions))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, "SkiaSharp.GRContextOptionsNative", "SkiaSharp")]
public SkiaMetalApi()
{
// Make sure that skia is loaded
GC.KeepAlive(new SKPaint());
// https://github.com/mono/SkiaSharp/blob/25e70a390e2128e5a54d28795365bf9fdaa7161c/binding/SkiaSharp/SkiaApi.cs#L9-L13
// Note, IsIOS also returns true on MacCatalyst.
var libSkiaSharpPath = OperatingSystemEx.IsIOS() || OperatingSystemEx.IsTvOS() ?
"@rpath/libSkiaSharp.framework/libSkiaSharp" :
"libSkiaSharp";
var dll = NativeLibraryEx.Load(libSkiaSharpPath, typeof(SKPaint).Assembly);
IntPtr address;
if (NativeLibraryEx.TryGetExport(dll, "gr_direct_context_make_metal_with_options", out address))
{
_gr_direct_context_make_metal_with_options =
(delegate* unmanaged[Stdcall] <IntPtr, IntPtr, IntPtr, IntPtr>)address;
}
else
{
throw new InvalidOperationException(
"Unable to export gr_direct_context_make_metal_with_options. Make sure SkiaSharp is up to date.");
}
if(NativeLibraryEx.TryGetExport(dll, "gr_backendrendertarget_new_metal", out address))
{
_gr_backendrendertarget_new_metal =
(delegate* unmanaged[Stdcall]<int, int, int, GRMtlTextureInfoNative*, IntPtr>)address;
}
else
{
throw new InvalidOperationException(
"Unable to export gr_backendrendertarget_new_metal. Make sure SkiaSharp is up to date.");
}
_contextCtor = typeof(GRContext).GetConstructor(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
new[] { typeof(IntPtr), typeof(bool) }, null) ?? throw new MissingMemberException("GRContext.ctor(IntPtr,bool)");
_renderTargetCtor = typeof(GRBackendRenderTarget).GetConstructor(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
new[] { typeof(IntPtr), typeof(bool) }, null) ?? throw new MissingMemberException("GRContext.ctor(IntPtr,bool)");
_contextOptionsToNative = typeof(GRContextOptions).GetMethod("ToNative",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
?? throw new MissingMemberException("GRContextOptions.ToNative()");
}
[UnconditionalSuppressMessage("Trimming", "IL3050", Justification = "We have DynamicDependency above.")]
public GRContext CreateContext(IntPtr device, IntPtr queue, GRContextOptions? options)
{
options ??= new();
var nativeOptions = _contextOptionsToNative.Invoke(options, null)!;
var gcHandle = GCHandle.Alloc(nativeOptions, GCHandleType.Pinned);
try
{
var context = _gr_direct_context_make_metal_with_options(device, queue, gcHandle.AddrOfPinnedObject());
if (context == IntPtr.Zero)
throw new InvalidOperationException("Unable to create GRContext from Metal device.");
return (GRContext)_contextCtor.Invoke(new object[] { context, true });
}
finally
{
gcHandle.Free();
}
}
internal struct GRMtlTextureInfoNative
{
public IntPtr Texture;
}
public GRBackendRenderTarget CreateBackendRenderTarget(int width, int height, int samples, IntPtr texture)
{
var info = new GRMtlTextureInfoNative() { Texture = texture };
var target = _gr_backendrendertarget_new_metal(width, height, samples, &info);
if (target == IntPtr.Zero)
throw new InvalidOperationException("Unable to create GRBackendRenderTarget");
return (GRBackendRenderTarget)_renderTargetCtor.Invoke(new object[] { target, true });
}
}

15
src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs

@ -9,14 +9,15 @@ namespace Avalonia.Skia.Metal;
internal class SkiaMetalGpu : ISkiaGpu, ISkiaGpuWithPlatformGraphicsContext
{
private SkiaMetalApi _api = new();
private GRContext? _context;
private readonly IMetalDevice _device;
public SkiaMetalGpu(IMetalDevice device, long? maxResourceBytes)
{
_context = _api.CreateContext(device.Device, device.CommandQueue,
new GRContextOptions() { AvoidStencilBuffers = true });
_context = GRContext.CreateMetal(
new GRMtlBackendContext { DeviceHandle = device.Device, QueueHandle = device.CommandQueue, },
new GRContextOptions { AvoidStencilBuffers = true })
?? throw new InvalidOperationException("Unable to create GRContext from Metal device.");
_device = device;
if (maxResourceBytes.HasValue)
_context.SetResourceCacheLimit(maxResourceBytes.Value);
@ -35,7 +36,7 @@ internal class SkiaMetalGpu : ISkiaGpu, ISkiaGpuWithPlatformGraphicsContext
public IPlatformGraphicsContext? PlatformGraphicsContext => _device;
public IScopedResource<GRContext> TryGetGrContext() =>
ScopedResource<GRContext>.Create(_context ?? throw new ObjectDisposedException(nameof(SkiaMetalApi)),
ScopedResource<GRContext>.Create(_context ?? throw new ObjectDisposedException(nameof(SkiaMetalGpu)),
EnsureCurrent().Dispose);
public ISkiaGpuRenderTarget? TryCreateRenderTarget(IEnumerable<object> surfaces)
@ -72,13 +73,13 @@ internal class SkiaMetalGpu : ISkiaGpu, ISkiaGpuWithPlatformGraphicsContext
public ISkiaGpuRenderSession BeginRenderingSession()
{
var session = (_target ?? throw new ObjectDisposedException(nameof(SkiaMetalRenderTarget))).BeginRendering();
var backendTarget = _gpu._api.CreateBackendRenderTarget(session.Size.Width, session.Size.Height,
1, session.Texture);
var backendTarget = new GRBackendRenderTarget(session.Size.Width, session.Size.Height,
new GRMtlTextureInfo(session.Texture));
var surface = SKSurface.Create(_gpu._context!, backendTarget,
session.IsYFlipped ? GRSurfaceOrigin.BottomLeft : GRSurfaceOrigin.TopLeft,
SKColorType.Bgra8888);
return new SkiaMetalRenderSession(_gpu, surface, session);
}

4
src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaExternalObjectsFeature.cs

@ -93,7 +93,7 @@ internal class VulkanSkiaExternalObjectsFeature : IExternalObjectsRenderInterfac
Size = info.MemorySize
}
};
using var renderTarget = new GRBackendRenderTarget(_properties.Width, _properties.Height, 1, imageInfo);
using var renderTarget = new GRBackendRenderTarget(_properties.Width, _properties.Height, imageInfo);
using var surface = SKSurface.Create(_gpu.GrContext, renderTarget,
_properties.TopLeftOrigin ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft,
_properties.Format == PlatformGraphicsExternalImageFormat.R8G8B8A8UNorm
@ -121,4 +121,4 @@ internal class VulkanSkiaExternalObjectsFeature : IExternalObjectsRenderInterfac
public IReadOnlyList<string> SupportedImageHandleTypes => _feature.SupportedImageHandleTypes;
public IReadOnlyList<string> SupportedSemaphoreTypes => _feature.SupportedSemaphoreTypes;
}
}

2
src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaRenderTarget.cs

@ -54,7 +54,7 @@ class VulkanSkiaRenderTarget : ISkiaGpuRenderTarget
Size = sessionImageInfo.MemorySize
}
};
using var renderTarget = new GRBackendRenderTarget(size.Width, size.Height, 1, imageInfo);
using var renderTarget = new GRBackendRenderTarget(size.Width, size.Height, imageInfo);
var surface = SKSurface.Create(_gpu.GrContext, renderTarget,
session.IsYFlipped ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft,
session.IsRgba ? SKColorType.Rgba8888 : SKColorType.Bgra8888, SKColorSpace.CreateSrgb());

3
src/Skia/Avalonia.Skia/IDrawableBitmapImpl.cs

@ -14,7 +14,8 @@ namespace Avalonia.Skia
/// <param name="context">Drawing context.</param>
/// <param name="sourceRect">Source rect.</param>
/// <param name="destRect">Destination rect.</param>
/// <param name="samplingOptions">Interpolation sampling options.</param>
/// <param name="paint">Paint to use.</param>
void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint);
void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKSamplingOptions samplingOptions, SKPaint paint);
}
}

10
src/Skia/Avalonia.Skia/ImmutableBitmap.cs

@ -50,7 +50,7 @@ namespace Avalonia.Skia
{
SKImageInfo info = new SKImageInfo(destinationSize.Width, destinationSize.Height, SKColorType.Bgra8888);
_bitmap = new SKBitmap(info);
src._image.ScalePixels(_bitmap.PeekPixels(), interpolationMode.ToSKFilterQuality());
src._image.ScalePixels(_bitmap.PeekPixels(), interpolationMode.ToSKSamplingOptions());
_bitmap.SetImmutable();
_image = SKImage.FromBitmap(_bitmap);
@ -95,11 +95,11 @@ namespace Avalonia.Skia
if (_bitmap.Width != desired.Width || _bitmap.Height != desired.Height)
{
var scaledBmp = _bitmap.Resize(desired, interpolationMode.ToSKFilterQuality());
var scaledBmp = _bitmap.Resize(desired, interpolationMode.ToSKSamplingOptions());
_bitmap.Dispose();
_bitmap = scaledBmp;
}
_bitmap.SetImmutable();
_image = SKImage.FromBitmap(_bitmap);
@ -171,9 +171,9 @@ namespace Avalonia.Skia
}
/// <inheritdoc />
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKSamplingOptions samplingOptions, SKPaint paint)
{
context.Canvas.DrawImage(_image, sourceRect, destRect, paint);
context.Canvas.DrawImage(_image, sourceRect, destRect, samplingOptions, paint);
}
public PixelFormat? Format => _bitmap?.ColorType.ToAvalonia();

56
src/Skia/Avalonia.Skia/SkiaSharpExtensions.cs

@ -9,22 +9,20 @@ namespace Avalonia.Skia
{
public static class SkiaSharpExtensions
{
public static SKFilterQuality ToSKFilterQuality(this BitmapInterpolationMode interpolationMode)
public static SKSamplingOptions ToSKSamplingOptions(this BitmapInterpolationMode interpolationMode)
{
switch (interpolationMode)
return interpolationMode switch
{
case BitmapInterpolationMode.Unspecified:
case BitmapInterpolationMode.LowQuality:
return SKFilterQuality.Low;
case BitmapInterpolationMode.MediumQuality:
return SKFilterQuality.Medium;
case BitmapInterpolationMode.HighQuality:
return SKFilterQuality.High;
case BitmapInterpolationMode.None:
return SKFilterQuality.None;
default:
throw new ArgumentOutOfRangeException(nameof(interpolationMode), interpolationMode, null);
}
BitmapInterpolationMode.None =>
new SKSamplingOptions(SKFilterMode.Nearest, SKMipmapMode.None),
BitmapInterpolationMode.Unspecified or BitmapInterpolationMode.LowQuality =>
new SKSamplingOptions(SKFilterMode.Linear, SKMipmapMode.None),
BitmapInterpolationMode.MediumQuality =>
new SKSamplingOptions(SKFilterMode.Linear, SKMipmapMode.Linear),
BitmapInterpolationMode.HighQuality =>
new SKSamplingOptions(SKCubicResampler.Mitchell),
_ => throw new ArgumentOutOfRangeException(nameof(interpolationMode), interpolationMode, null)
};
}
public static SKBlendMode ToSKBlendMode(this BitmapBlendingMode blendingMode)
@ -146,11 +144,41 @@ namespace Avalonia.Skia
return sm;
}
public static SKMatrix44 ToSKMatrix44(this Matrix m)
{
var sm = new SKMatrix44
{
M00 = (float)m.M11,
M01 = (float)m.M12,
M02 = 0,
M03 = (float)m.M13,
M10 = (float)m.M21,
M11 = (float)m.M22,
M12 = 0,
M13 = (float)m.M23,
M20 = 0,
M21 = 0,
M22 = 1,
M23 = 0,
M30 = (float)m.M31,
M31 = (float)m.M32,
M32 = 0,
M33 = (float)m.M33
};
return sm;
}
internal static Matrix ToAvaloniaMatrix(this SKMatrix m) => new(
m.ScaleX, m.SkewY, m.Persp0,
m.SkewX, m.ScaleY, m.Persp1,
m.TransX, m.TransY, m.Persp2);
internal static Matrix ToAvaloniaMatrix(this SKMatrix44 m) => new(
m.M00, m.M01, m.M03,
m.M10, m.M11, m.M13,
m.M30, m.M31, m.M33);
public static SKColor ToSKColor(this Color c)
{
return new SKColor(c.R, c.G, c.B, c.A);

7
src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs

@ -2,7 +2,6 @@ using System;
using System.IO;
using Avalonia.Reactive;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Skia.Helpers;
using SkiaSharp;
@ -164,12 +163,12 @@ namespace Avalonia.Skia
public bool CanBlit => true;
/// <inheritdoc />
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKSamplingOptions samplingOptions, SKPaint paint)
{
using var image = SnapshotImage();
context.Canvas.DrawImage(image, sourceRect, destRect, paint);
context.Canvas.DrawImage(image, sourceRect, destRect, samplingOptions, paint);
}
/// <summary>
/// Create Skia image snapshot from a surface.
/// </summary>

6
src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs

@ -73,7 +73,7 @@ namespace Avalonia.Skia
if (bmp.Width != desired.Width || bmp.Height != desired.Height)
{
var scaledBmp = bmp.Resize(desired, interpolationMode.ToSKFilterQuality());
var scaledBmp = bmp.Resize(desired, interpolationMode.ToSKSamplingOptions());
bmp.Dispose();
bmp = scaledBmp;
}
@ -118,7 +118,7 @@ namespace Avalonia.Skia
public int Version { get; private set; } = 1;
/// <inheritdoc />
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKSamplingOptions samplingOptions, SKPaint paint)
{
lock (_lock)
{
@ -132,7 +132,7 @@ namespace Avalonia.Skia
_image = GetSnapshot();
_imageValid = true;
}
context.Canvas.DrawImage(_image, sourceRect, destRect, paint);
context.Canvas.DrawImage(_image, sourceRect, destRect, samplingOptions, paint);
}
}

12
src/iOS/Avalonia.iOS/Metal/MetalPlatformGraphics.cs

@ -2,7 +2,6 @@ using System;
using System.Runtime.Versioning;
using Avalonia.Platform;
using Metal;
using SkiaSharp;
namespace Avalonia.iOS.Metal;
@ -33,17 +32,6 @@ internal class MetalPlatformGraphics : IPlatformGraphics
return null;
}
#if !TVOS
using var queue = device.CreateCommandQueue();
using var context = GRContext.CreateMetal(new GRMtlBackendContext { Device = device, Queue = queue });
if (context is null)
{
// Can be null on macCatalyst because of older Skia bug.
// Fixed in SkiaSharp 3.0
return null;
}
#endif
return new MetalPlatformGraphics(device);
}
}

6
tests/Avalonia.RenderTests/TestBase.cs

@ -42,13 +42,7 @@ namespace Avalonia.Direct2D1.RenderTests
#endif
public static FontFamily TestFontFamily = new FontFamily(s_fontUri);
#if AVALONIA_SKIA3
// TODO: investigate why output is different.
// Most likely we need to use new SKSamplingOptions API, as old filters are broken with SKBitmap.
private const double AllowedError = 0.15;
#else
private const double AllowedError = 0.022;
#endif
public TestBase(string outputPath)
{

5
tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj

@ -5,11 +5,6 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IncludeLinuxSkia>true</IncludeLinuxSkia>
<IncludeWasmSkia>true</IncludeWasmSkia>
<!-- <AvaSkiaRenderTestsIncludeSkiaSharp3>true</AvaSkiaRenderTestsIncludeSkiaSharp3>-->
<AvsIncludeSkiaSharp3 Condition="'$(AvsIncludeSkiaSharp3)' == '' AND '$(AvaSkiaRenderTestsIncludeSkiaSharp3)' == 'true'">true</AvsIncludeSkiaSharp3>
<DefineConstants Condition="'$(AvsIncludeSkiaSharp3)' == 'true'">$(DefineConstants);AVALONIA_SKIA3</DefineConstants>
<DefineConstants Condition="'$(AvsIncludeSkiaSharp3)' != 'true'">$(DefineConstants);AVALONIA_SKIA2</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.RenderTests\**\*.cs" />

Loading…
Cancel
Save