From 92bb8371cdbb4351966c6a8a71e4e09ef7b85782 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Sat, 2 Mar 2024 22:05:24 +0200 Subject: [PATCH 1/3] Use Unsafe.As for better perf Fixes #2778 --- binding/Directory.Build.targets | 4 + binding/SkiaSharp/SKMatrix44.cs | 65 +++---- externals/skia | 2 +- tests/Tests/SkiaSharp/SKMatrix44Tests.cs | 237 +++++++++++++++-------- 4 files changed, 189 insertions(+), 119 deletions(-) diff --git a/binding/Directory.Build.targets b/binding/Directory.Build.targets index f6e780a0ff..813aac0552 100644 --- a/binding/Directory.Build.targets +++ b/binding/Directory.Build.targets @@ -4,6 +4,10 @@ + + + + SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images. diff --git a/binding/SkiaSharp/SKMatrix44.cs b/binding/SkiaSharp/SKMatrix44.cs index dfbe3754df..8c44538d4a 100644 --- a/binding/SkiaSharp/SKMatrix44.cs +++ b/binding/SkiaSharp/SKMatrix44.cs @@ -2,6 +2,7 @@ using System; using System.Numerics; +using System.Runtime.CompilerServices; namespace SkiaSharp { @@ -348,46 +349,46 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) => public SKMatrix Matrix => new SKMatrix ( - m00, m01, m03, - m10, m11, m13, - m30, m31, m33); + m00, m10, m30, + m01, m11, m31, + m03, m13, m33); public float this[int row, int column] { - get => column switch { - 0 => row switch { + get => row switch { + 0 => column switch { 0 => m00, 1 => m01, 2 => m02, 3 => m03, - _ => throw new ArgumentOutOfRangeException (nameof (row)) + _ => throw new ArgumentOutOfRangeException (nameof (column)) }, - 1 => row switch { + 1 => column switch { 0 => m10, 1 => m11, 2 => m12, 3 => m13, - _ => throw new ArgumentOutOfRangeException (nameof (row)) + _ => throw new ArgumentOutOfRangeException (nameof (column)) }, - 2 => row switch { + 2 => column switch { 0 => m20, 1 => m21, 2 => m22, 3 => m23, - _ => throw new ArgumentOutOfRangeException (nameof (row)) + _ => throw new ArgumentOutOfRangeException (nameof (column)) }, - 3 => row switch { + 3 => column switch { 0 => m30, 1 => m31, 2 => m32, 3 => m33, - _ => throw new ArgumentOutOfRangeException (nameof (row)) + _ => throw new ArgumentOutOfRangeException (nameof (column)) }, - _ => throw new ArgumentOutOfRangeException (nameof (column)) + _ => throw new ArgumentOutOfRangeException (nameof (row)) }; set { - switch (column) { + switch (row) { case 0: - switch (row) { + switch (column) { case 0: m00 = value; break; @@ -401,11 +402,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) => m03 = value; break; default: - throw new ArgumentOutOfRangeException (nameof (row)); + throw new ArgumentOutOfRangeException (nameof (column)); }; break; case 1: - switch (row) { + switch (column) { case 0: m10 = value; break; @@ -419,11 +420,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) => m13 = value; break; default: - throw new ArgumentOutOfRangeException (nameof (row)); + throw new ArgumentOutOfRangeException (nameof (column)); }; break; case 2: - switch (row) { + switch (column) { case 0: m20 = value; break; @@ -437,11 +438,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) => m23 = value; break; default: - throw new ArgumentOutOfRangeException (nameof (row)); + throw new ArgumentOutOfRangeException (nameof (column)); }; break; case 3: - switch (row) { + switch (column) { case 0: m30 = value; break; @@ -455,11 +456,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) => m33 = value; break; default: - throw new ArgumentOutOfRangeException (nameof (row)); + throw new ArgumentOutOfRangeException (nameof (column)); }; break; default: - throw new ArgumentOutOfRangeException (nameof (column)); + throw new ArgumentOutOfRangeException (nameof (row)); }; } } @@ -468,23 +469,15 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) => public static implicit operator SKMatrix44 (SKMatrix matrix) => new SKMatrix44 ( - matrix.ScaleX, matrix.SkewX, 0, matrix.TransX, - matrix.SkewY, matrix.ScaleY, 0, matrix.TransY, + matrix.ScaleX, matrix.SkewY, 0, matrix.Persp0, + matrix.SkewX, matrix.ScaleY, 0, matrix.Persp1, 0, 0, 1, 0, - matrix.Persp0, matrix.Persp1, 0, matrix.Persp2); + matrix.TransX, matrix.TransY, 0, matrix.Persp2); public static implicit operator Matrix4x4 (SKMatrix44 matrix) => - new Matrix4x4 ( - matrix.m00, matrix.m10, matrix.m20, matrix.m30, - matrix.m01, matrix.m11, matrix.m21, matrix.m31, - matrix.m02, matrix.m12, matrix.m22, matrix.m32, - matrix.m03, matrix.m13, matrix.m23, matrix.m33); + Unsafe.As (ref matrix); public static implicit operator SKMatrix44 (Matrix4x4 matrix) => - new SKMatrix44 ( - matrix.M11, matrix.M21, matrix.M31, matrix.M41, - matrix.M12, matrix.M22, matrix.M32, matrix.M42, - matrix.M13, matrix.M23, matrix.M33, matrix.M43, - matrix.M14, matrix.M24, matrix.M34, matrix.M44); + Unsafe.As (ref matrix); } } diff --git a/externals/skia b/externals/skia index 53d2065ea8..bb74fbc120 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit 53d2065ea8724daeb85e839ba47f54c582809615 +Subproject commit bb74fbc120c186de186f7e575e83cac184d3a030 diff --git a/tests/Tests/SkiaSharp/SKMatrix44Tests.cs b/tests/Tests/SkiaSharp/SKMatrix44Tests.cs index f8dc0ac381..371b81f759 100644 --- a/tests/Tests/SkiaSharp/SKMatrix44Tests.cs +++ b/tests/Tests/SkiaSharp/SKMatrix44Tests.cs @@ -60,6 +60,74 @@ public void MatrixGoesFullCircle() Assert.Equal(rowMajor, result); } + [SkippableFact] + public void TranslationFieldsAreCorrectForMatrix() + { + var skm44 = SKMatrix44.CreateTranslation(10, 20, 30); + + var matrix = skm44.Matrix; + + Assert.Equal(10, matrix.TransX); + Assert.Equal(20, matrix.TransY); + } + + [SkippableFact] + public void ScaleFieldsAreCorrectForMatrix() + { + var skm44 = SKMatrix44.CreateScale(10, 20, 30); + + var matrix = skm44.Matrix; + + Assert.Equal(10, matrix.ScaleX); + Assert.Equal(20, matrix.ScaleY); + } + + [SkippableFact] + public void TranslateConvertsToMatrix() + { + var matrix44 = SKMatrix44.CreateTranslation(10, 20, 30); + var matrix = SKMatrix.CreateTranslation(10, 20); + + AssertSimilar(matrix.Values, matrix44.Matrix.Values, 6); + } + + [SkippableFact] + public void ScaleConvertsToMatrix() + { + var matrix44 = SKMatrix44.CreateScale(10, 20, 30); + var matrix = SKMatrix.CreateScale(10, 20); + + AssertSimilar(matrix.Values, matrix44.Matrix.Values, 6); + } + + [SkippableFact] + public void RotationConvertsToMatrix() + { + var matrix44 = SKMatrix44.CreateRotationDegrees(0, 0, 1, 45); + var matrix = SKMatrix.CreateRotationDegrees(45); + + AssertSimilar(matrix.Values, matrix44.Matrix.Values, 6); + } + + [SkippableFact] + public void ImplicitFromMatrix() + { + var matrix = SKMatrix.CreateRotationDegrees(45); + var matrix44 = (SKMatrix44)matrix; + + Assert.Equal(matrix.Values, matrix44.Matrix.Values); + } + + [SkippableFact] + public void ImplicitFromRotationScale() + { + var rs = SKRotationScaleMatrix.CreateRotationDegrees(45, 0, 0); + var matrix = SKMatrix.CreateRotationDegrees(45); + var matrix44 = (SKMatrix44)rs.ToMatrix(); + + Assert.Equal(matrix.Values, matrix44.Matrix.Values); + } + [SkippableFact] public void TransposeWorks() { @@ -136,108 +204,32 @@ public void Matrix44Inverts() } [SkippableFact] - public void Matrix44ConvertsToMatrix() - { - var rowMajor44 = new float[] { - 2, 3, 4, 5, - 4, 6, 8, 10, - 6, 9, 12, 15, - 8, 12, 16, 20, - }; - var rowMajor = new float[] { - rowMajor44[0], rowMajor44[1], rowMajor44[3], - rowMajor44[4], rowMajor44[5], rowMajor44[7], - rowMajor44[12], rowMajor44[13], rowMajor44[15], - }; - - var matrix44 = SKMatrix44.FromRowMajor(rowMajor44); - - Assert.Equal(rowMajor, matrix44.Matrix.Values); - } - - [SkippableFact] - public void TransformConvertsToMatrix() - { - var matrix44 = SKMatrix44.CreateRotationDegrees(0, 0, 1, 45); - var matrix = SKMatrix.CreateRotationDegrees(45); - - AssertSimilar(matrix.Values, matrix44.Matrix.Values, 6); - } - - [SkippableFact] - public void ImplicitFromMatrix() - { - var matrix = SKMatrix.CreateRotationDegrees(45); - var matrix44 = (SKMatrix44)matrix; - - Assert.Equal(matrix.Values, matrix44.Matrix.Values); - } - - [SkippableFact] - public void ImplicitFromRotationScale() - { - var rs = SKRotationScaleMatrix.CreateRotationDegrees(45, 0, 0); - var matrix = SKMatrix.CreateRotationDegrees(45); - var matrix44 = (SKMatrix44)rs.ToMatrix(); - - Assert.Equal(matrix.Values, matrix44.Matrix.Values); - } - -#if NET5_0_OR_GREATER - - [SkippableFact] - public void IndicesAreCorrectOnIdentity() + public void IndicesAreCorrectOnIdentityUsingFields() { var skm = SKMatrix44.CreateIdentity(); var m4x4 = Matrix4x4.Identity; - for (var row = 0; row < 4; row++) - { - for (var col = 0; col < 4; col++) - { - var sk = skm[row, col]; - var m = m4x4[row, col]; - Assert.Equal(m, sk); - } - } + AssertEqualFields(skm, m4x4); } [SkippableFact] - public void IndicesAreCorrectOnTranslate() + public void IndicesAreCorrectOnTranslateUsingFields() { var skm = SKMatrix44.CreateTranslation(10, 20, 30); var m4x4 = Matrix4x4.CreateTranslation(10, 20, 30); - for (var row = 0; row < 4; row++) - { - for (var col = 0; col < 4; col++) - { - var sk = skm[row, col]; - var m = m4x4[row, col]; - Assert.Equal(m, sk); - } - } + AssertEqualFields(skm, m4x4); } [SkippableFact] - public void IndicesAreCorrectOnScale() + public void IndicesAreCorrectOnScaleUsingFields() { var skm = SKMatrix44.CreateScale(10, 20, 30); var m4x4 = Matrix4x4.CreateScale(10, 20, 30); - for (var row = 0; row < 4; row++) - { - for (var col = 0; col < 4; col++) - { - var sk = skm[row, col]; - var m = m4x4[row, col]; - Assert.Equal(m, sk); - } - } + AssertEqualFields(skm, m4x4); } -#endif - [SkippableFact] public void TranslationMapsScalars() { @@ -350,6 +342,87 @@ public void ScaleIsCorrectLayoutWithOriginTopLeft(int x, int y, int z) AssertMatrixBitmap(bmp, SKRectI.Create(30 * x, 30 * y, 10 * x, 10 * y)); } + [SkippableTheory] + [InlineData(1, 0, 0, 30)] + [InlineData(0, 1, 0, 30)] + [InlineData(0, 0, 1, 30)] + [InlineData(1, 0, 0, -30)] + [InlineData(0, 1, 0, -30)] + [InlineData(0, 0, 1, -30)] + public void RotationIsCorrectLayoutWithOriginTopLeft(int x, int y, int z, int angle) + { + var matrix = SKMatrix44.CreateRotationDegrees(x, y, z, angle); + + using var bmp = DrawMatrixBitmap(SKRectI.Create(25, 25, 50, 50), matrix); + } + +#if NET5_0_OR_GREATER + + [SkippableFact] + public void IndicesAreCorrectOnIdentity() + { + var skm = SKMatrix44.CreateIdentity(); + var m4x4 = Matrix4x4.Identity; + + AssertEqualIndices(skm, m4x4); + } + + [SkippableFact] + public void IndicesAreCorrectOnTranslate() + { + var skm = SKMatrix44.CreateTranslation(10, 20, 30); + var m4x4 = Matrix4x4.CreateTranslation(10, 20, 30); + + AssertEqualIndices(skm, m4x4); + } + + [SkippableFact] + public void IndicesAreCorrectOnScale() + { + var skm = SKMatrix44.CreateScale(10, 20, 30); + var m4x4 = Matrix4x4.CreateScale(10, 20, 30); + + AssertEqualIndices(skm, m4x4); + } + + private static void AssertEqualIndices(SKMatrix44 skm, Matrix4x4 m4x4) + { + for (var row = 0; row < 4; row++) + { + for (var col = 0; col < 4; col++) + { + var sk = skm[row, col]; + var m = m4x4[row, col]; + Assert.Equal(m, sk); + } + } + } + +#endif + + private static void AssertEqualFields(SKMatrix44 skm, Matrix4x4 m4x4) + { + Assert.Equal(skm.M00, m4x4.M11); + Assert.Equal(skm.M01, m4x4.M12); + Assert.Equal(skm.M02, m4x4.M13); + Assert.Equal(skm.M03, m4x4.M14); + + Assert.Equal(skm.M10, m4x4.M21); + Assert.Equal(skm.M11, m4x4.M22); + Assert.Equal(skm.M12, m4x4.M23); + Assert.Equal(skm.M13, m4x4.M24); + + Assert.Equal(skm.M20, m4x4.M31); + Assert.Equal(skm.M21, m4x4.M32); + Assert.Equal(skm.M22, m4x4.M33); + Assert.Equal(skm.M23, m4x4.M34); + + Assert.Equal(skm.M30, m4x4.M41); + Assert.Equal(skm.M31, m4x4.M42); + Assert.Equal(skm.M32, m4x4.M43); + Assert.Equal(skm.M33, m4x4.M44); + } + private static SKBitmap DrawMatrixBitmap(SKRect rect, SKMatrix44 matrix) { var bmp = new SKBitmap(100, 100); From 036433ebcdd38302024a425fa6c3a0fe7b3064c4 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 4 Mar 2024 17:57:27 +0200 Subject: [PATCH 2/3] oops --- externals/skia | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/skia b/externals/skia index bb74fbc120..f1e052377a 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit bb74fbc120c186de186f7e575e83cac184d3a030 +Subproject commit f1e052377a3426250616af89ce51ff249e383e31 From 1a55cd23f0588a00bb21183d9b586a70308c2b2b Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 4 Mar 2024 21:27:45 +0200 Subject: [PATCH 3/3] Update externals after the merge --- externals/skia | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/skia b/externals/skia index f1e052377a..a0008792c8 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit f1e052377a3426250616af89ce51ff249e383e31 +Subproject commit a0008792c861228872a0a21f5f3422c4c8824720