Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jul 5, 2025
Merged

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

merged 12 commits into from
Jul 5, 2025

Conversation

maxkatz6
Copy link
Member

@maxkatz6 maxkatz6 commented Jun 3, 2025

What does the pull request do?

For the last year, 11.x builds were compatible with both 2.88 and 3.0 SkiaSharp versions.
Half a year ago, SkiaSharp 3.0 had first stable release.
And now it's time to drop 2.88 support on the Avalonia side.

Note, this PR is not going to be backported to 11.x versions.

How was the solution implemented (if it's not obvious)?

  1. Bump version
  2. Replace obsolete APIs with new alternatives. Primarily SKSamplingOptions.
  3. New APIs for Metal instead of reflection

Breaking changes

Any app or dependency that uses SkiaSharp APIs that are not binary compatible with SkiaSharp 3.0 will break.
It should not affect majority of applications. And even with Skia dependent controls like LiveCharts2 are already compatible with SkiaSharp3.

Fixed issues

Closes #15503
Fixes #17735
Fixes #18677

@maxkatz6 maxkatz6 added this to the 12.0 milestone Jun 3, 2025
@maxkatz6 maxkatz6 requested a review from kekekeks June 3, 2025 04:16
Comment on lines +12 to +25
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)
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rabbitism
Copy link
Contributor

also this #18677

@drasticactions
Copy link
Contributor

drasticactions commented Jun 6, 2025

@maxkatz6 This PR doesn't work with iOS right now,

https://gist.github.com/drasticactions/e964b2445a55752b8618dc89359fc338

MetalPlatformGraphics.TryCreate returns null, leading to it being disposed, leading to a crash on startup. If you deploy the ControlCatalog.iOS project, you should hit it.

e. I think I figured it out. The code in that TryCreate method that calls GRContext.CreateMetal (which isn't used and is disposed when the method is returned) is causing it to short-circuit, leading to a native error. I don't believe this code is needed. The actual GRContext.CreateMetal is created elsewhere in SkiaMetalGpu after initialization, where if this context can't be created, it should blow up then.

If you replace that method with

    public static MetalPlatformGraphics? TryCreate()
    {
        var device = MTLDevice.SystemDefault;
        return device is null ? null : new MetalPlatformGraphics(device);
    }

It works.

image

e2. Adding my change and re-adding Catalyst TFM as a target, Catalyst also works (Although some input stuff would need to be looked at, like scroll wheels for the list didn't work.)

Catalyst.mp4

@kekekeks
Copy link
Member

kekekeks commented Jun 6, 2025

The iOS crash is a double dispose bug in SkiaSharp.

@maxkatz6
Copy link
Member Author

maxkatz6 commented Jul 5, 2025

e. I think I figured it out. The code in that TryCreate method that calls GRContext.CreateMetal (which isn't used and is disposed when the method is returned) is causing it to short-circuit, leading to a native error.

IIRC, this extra metal context was used to validate whether metal is working fine, or fallback to opengl otherwise. These were issues in 2.88 where it could return null (I think maccatalyst or tvos related?). Either way, it should be removed now.

Upd: yep, I even left a comment there for the future me:

// Can be null on macCatalyst because of older Skia bug.
// Fixed in SkiaSharp 3.0

Definitely should remove it now.

@drasticactions
Copy link
Contributor

drasticactions commented Jul 5, 2025

With 7f1a4d1, it fixes the iOS/Catalyst SkiaSharp 3.x issue and I can use it there,

For #19028, I bumped my repro and the users repro to this version (on a different machine than what I originally had), built and ran it, and it worked. IMO we need more confirmation from them to make sure it works right on macOS 26 (since I was able to somehow get it working with no changes after originally get the same crash, and I'm not sure how I did that yet). But the changes to the bindings didn't regress it so I think it's safe in that context.

@maxkatz6 maxkatz6 added this pull request to the merge queue Jul 5, 2025
Merged via the queue into master with commit b644cee Jul 5, 2025
11 checks passed
@maxkatz6 maxkatz6 deleted the skiasharp-3.0 branch July 5, 2025 08:28
@MrJul MrJul mentioned this pull request Jul 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants