diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 82df7304e5..190cedfdd2 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -1,12 +1,15 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System.Numerics; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.ImageSharp.Processing.Processors.Quantization; +using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.Primitives; namespace SixLabors.ImageSharp.Advanced { @@ -15,8 +18,10 @@ namespace SixLabors.ImageSharp.Advanced /// compiled on demand by a JIT compiler. This means there are a few limitations with respect to generics, /// these are caused because not every possible generic instantiation can be determined up front at compile time. /// The Aot Compiler is designed to overcome the limitations of this compiler. + /// None of the methods in this class should ever be called, the code only has to exist at compile-time to be picked up by the AoT compiler. + /// (Very similar to the LinkerIncludes.cs technique used in Xamarin.Android projects.) /// - public static class AotCompilerTools + internal static class AotCompilerTools { static AotCompilerTools() { @@ -25,21 +30,59 @@ static AotCompilerTools() System.Runtime.CompilerServices.Unsafe.SizeOf(); System.Runtime.CompilerServices.Unsafe.SizeOf(); System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); System.Runtime.CompilerServices.Unsafe.SizeOf(); System.Runtime.CompilerServices.Unsafe.SizeOf(); } + /// + /// This is the method that seeds the AoT compiler. + /// None of these seed methods needs to actually be called to seed the compiler. + /// The calls just need to be present when the code is compiled, and each implementation will be built. + /// + private static void SeedEverything() + { + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + Seed(); + } + /// /// Seeds the compiler using the given pixel format. /// /// The pixel format. - public static void Seed() + private static void Seed() where TPixel : struct, IPixel { // This is we actually call all the individual methods you need to seed. AotCompileOctreeQuantizer(); AotCompileWuQuantizer(); AotCompileDithering(); + AotCompilePixelOperations(); + AotCompileResizeOperations(); System.Runtime.CompilerServices.Unsafe.SizeOf(); @@ -51,34 +94,6 @@ public static void Seed() // TODO: Do the discovery work to figure out what works and what doesn't. } - /// - /// Seeds the compiler using the given pixel formats. - /// - /// The first pixel format. - /// The second pixel format. - public static void Seed() - where TPixel : struct, IPixel - where TPixel2 : struct, IPixel - { - Seed(); - Seed(); - } - - /// - /// Seeds the compiler using the given pixel formats. - /// - /// The first pixel format. - /// The second pixel format. - /// The third pixel format. - public static void Seed() - where TPixel : struct, IPixel - where TPixel2 : struct, IPixel - where TPixel3 : struct, IPixel - { - Seed(); - Seed(); - } - /// /// This method doesn't actually do anything but serves an important purpose... /// If you are running ImageSharp on iOS and try to call SaveAsGif, it will throw an excepion: @@ -146,5 +161,28 @@ private static void AotCodec(IImageDecoder decoder, IImageEncoder encode { } } + + /// + /// This method pre-seeds the PixelOperations engine for the AoT compiler on iOS. + /// + /// The pixel format. + private static void AotCompilePixelOperations() + where TPixel : struct, IPixel + { + var pixelOp = new PixelOperations(); + pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear); + } + + /// + /// This method pre-seeds the ResizeProcessor for the AoT compiler on iOS. + /// + /// The pixel format. + private static void AotCompileResizeOperations() + where TPixel : struct, IPixel + { + var resizeProcessor = new ResizeProcessor(new ResizeOptions(), new Size()); + var genericResizeProcessor = new ResizeProcessor(resizeProcessor.CreatePixelSpecificProcessor() as ResizeProcessor); + genericResizeProcessor.AotCreateDestination(new Image(0, 0), new Rectangle()); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index fb03057a48..cb30067401 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -64,6 +64,15 @@ public ResizeProcessor(ResizeProcessor parameterSource) /// public bool Compand => this.parameterSource.Compand; + /// + /// This is a shim for tagging the CreateDestination virtual generic method for the AoT iOS compiler. + /// This method should never be referenced outside of the AotCompiler code. + /// + /// Passed through as source to the CreateDestination method. + /// Passed through as sourceRectangle to the CreateDestination method. + /// The result returned from CreateDestination. + internal Image AotCreateDestination(Image source, Rectangle sourceRectangle) => this.CreateDestination(source, sourceRectangle); + /// protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { @@ -188,4 +197,4 @@ protected override void AfterImageApply(Image source, Image dest this.verticalKernelMap = null; } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Advanced/AotCompilerTests.cs b/tests/ImageSharp.Tests/Advanced/AotCompilerTests.cs deleted file mode 100644 index f6397dbd09..0000000000 --- a/tests/ImageSharp.Tests/Advanced/AotCompilerTests.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Advanced -{ - public class AotCompilerTests - { - [Fact] - public void AotCompiler_NoExceptions() => AotCompilerTools.Seed(); - } -}