diff --git a/VERSIONS.txt b/VERSIONS.txt
index 85e844f4e0..d94e0af097 100644
--- a/VERSIONS.txt
+++ b/VERSIONS.txt
@@ -68,6 +68,7 @@ SkiaSharp.NativeAssets.tvOS nuget 2.88.9
SkiaSharp.NativeAssets.UWP nuget 2.88.9
SkiaSharp.NativeAssets.watchOS nuget 2.88.9
SkiaSharp.NativeAssets.Win32 nuget 2.88.9
+SkiaSharp.NativeAssets.WinUI nuget 2.88.9
SkiaSharp.Views nuget 2.88.9
SkiaSharp.Views.NativeAssets.UWP nuget 2.88.9
SkiaSharp.Views.Desktop.Common nuget 2.88.9
diff --git a/binding/IncludeNativeAssets.SkiaSharp.WinUI.targets b/binding/IncludeNativeAssets.SkiaSharp.WinUI.targets
new file mode 100644
index 0000000000..3ad22b628c
--- /dev/null
+++ b/binding/IncludeNativeAssets.SkiaSharp.WinUI.targets
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binding/SkiaSharp/SkiaSharp.csproj b/binding/SkiaSharp/SkiaSharp.csproj
index 96844c9563..d99b375403 100644
--- a/binding/SkiaSharp/SkiaSharp.csproj
+++ b/binding/SkiaSharp/SkiaSharp.csproj
@@ -17,6 +17,13 @@
+
+
+
+
+
+
+
diff --git a/build.cake b/build.cake
index a6e2ffc0ca..3d4eaf8b64 100644
--- a/build.cake
+++ b/build.cake
@@ -80,6 +80,7 @@ var TRACKED_NUGETS = new Dictionary {
{ "SkiaSharp.NativeAssets.UWP", new Version (1, 60, 0) },
{ "SkiaSharp.NativeAssets.watchOS", new Version (1, 60, 0) },
{ "SkiaSharp.NativeAssets.Win32", new Version (1, 60, 0) },
+ { "SkiaSharp.NativeAssets.WinUI", new Version (1, 60, 0) },
{ "SkiaSharp.Views", new Version (1, 60, 0) },
{ "SkiaSharp.Views.NativeAssets.UWP", new Version (1, 60, 0) },
{ "SkiaSharp.Views.Desktop.Common", new Version (1, 60, 0) },
diff --git a/externals/.gitignore b/externals/.gitignore
index df5b644fa9..d83a461853 100644
--- a/externals/.gitignore
+++ b/externals/.gitignore
@@ -1,3 +1,4 @@
angle/
package_cache/
vcpkg/
+winappsdk/
diff --git a/externals/skia b/externals/skia
index 30b08b827c..4bed689c9c 160000
--- a/externals/skia
+++ b/externals/skia
@@ -1 +1 @@
-Subproject commit 30b08b827c7c8ab154818f4dbe26a984a9a371da
+Subproject commit 4bed689c9c9eb77a120c6a9d54af6a572c85d1c2
diff --git a/native/.gitignore b/native/.gitignore
index 2a4fe393c9..2f11c1ce72 100644
--- a/native/.gitignore
+++ b/native/.gitignore
@@ -1,3 +1,4 @@
xcuserdata/
project.xcworkspace/
uwp/ANGLE/triplets
+Generated Files/
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.props b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.props
new file mode 100644
index 0000000000..67ea2536c9
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.props
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.targets b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.targets
new file mode 100644
index 0000000000..3d8b24a04d
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/SkiaSharp.Views.WinUI.Native.Projection.csproj b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/SkiaSharp.Views.WinUI.Native.Projection.csproj
new file mode 100644
index 0000000000..ecfce99664
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/SkiaSharp.Views.WinUI.Native.Projection.csproj
@@ -0,0 +1,26 @@
+
+
+
+ $(WindowsTargetFrameworks)
+ 10.0.17763.0
+ SkiaSharp.Views.WinUI
+ SkiaSharp.Views.WinUI
+ false
+ enable
+ enable
+
+
+
+ None
+ SkiaSharp.Views.WinUI.Native
+
+
+
+
+
+
+
+
+
+
+
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln
new file mode 100644
index 0000000000..0435478c90
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln
@@ -0,0 +1,61 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34310.174
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SkiaSharp.Views.WinUI.Native", "SkiaSharp.Views.WinUI.Native\SkiaSharp.Views.WinUI.Native.vcxproj", "{730AF4C9-82D2-4FA7-AA32-154F3524EBD2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.WinUI.Native.Projection", "SkiaSharp.Views.WinUI.Native.Projection\SkiaSharp.Views.WinUI.Native.Projection.csproj", "{95E9FEB4-DCD3-4514-8208-A87688788BB2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|Any CPU.Build.0 = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|ARM64.Build.0 = Debug|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x64.ActiveCfg = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x64.Build.0 = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x86.ActiveCfg = Debug|Win32
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x86.Build.0 = Debug|Win32
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|Any CPU.ActiveCfg = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|Any CPU.Build.0 = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|ARM64.ActiveCfg = Release|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|ARM64.Build.0 = Release|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x64.ActiveCfg = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x64.Build.0 = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x86.ActiveCfg = Release|Win32
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x86.Build.0 = Release|Win32
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x64.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x86.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|ARM64.Build.0 = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x64.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x64.Build.0 = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x86.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FB8DA12F-84B5-4D7F-A6E1-7F0A53AA4535}
+ EndGlobalSection
+EndGlobal
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.cpp b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.cpp
new file mode 100644
index 0000000000..5d1c886f22
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.cpp
@@ -0,0 +1,16 @@
+#include "pch.h"
+#include "BufferExtensions.h"
+#include "BufferExtensions.g.cpp"
+
+using namespace winrt::Windows::Storage::Streams;
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::implementation
+{
+ intptr_t BufferExtensions::GetByteBuffer(IBuffer const& buffer)
+ {
+ byte* current_data = nullptr;
+ auto bufferByteAccess = buffer.as();
+ bufferByteAccess->Buffer(¤t_data);
+ return (intptr_t)current_data;
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.h b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.h
new file mode 100644
index 0000000000..007b128952
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "BufferExtensions.g.h"
+
+using namespace winrt::Windows::Storage::Streams;
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::implementation
+{
+ struct BufferExtensions
+ {
+ BufferExtensions() = default;
+
+ static intptr_t GetByteBuffer(IBuffer const& buffer);
+ };
+}
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::factory_implementation
+{
+ struct BufferExtensions : BufferExtensionsT
+ {
+ };
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.idl b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.idl
new file mode 100644
index 0000000000..b47b1df880
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/BufferExtensions.idl
@@ -0,0 +1,7 @@
+namespace SkiaSharp.Views.WinUI.Native
+{
+ static runtimeclass BufferExtensions
+ {
+ static Int64 GetByteBuffer(Windows.Storage.Streams.IBuffer buffer);
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.cpp b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.cpp
new file mode 100644
index 0000000000..c2174e6cf7
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.cpp
@@ -0,0 +1,19 @@
+#include "pch.h"
+#include "PropertySetExtensions.h"
+#include "PropertySetExtensions.g.cpp"
+
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::implementation
+{
+ void PropertySetExtensions::AddSingle(PropertySet const& propertySet, hstring const& key, float value)
+ {
+ propertySet.Insert(key, PropertyValue::CreateSingle(value));
+ }
+
+ void PropertySetExtensions::AddSize(PropertySet const& propertySet, hstring const& key, Size const& height)
+ {
+ propertySet.Insert(key, PropertyValue::CreateSize(height));
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.h b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.h
new file mode 100644
index 0000000000..de60e32b45
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "PropertySetExtensions.g.h"
+
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::implementation
+{
+ struct PropertySetExtensions
+ {
+ PropertySetExtensions() = default;
+
+ static void AddSingle(PropertySet const& propertySet, hstring const& key, float value);
+ static void AddSize(PropertySet const& propertySet, hstring const& key, Size const& value);
+ };
+}
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::factory_implementation
+{
+ struct PropertySetExtensions : PropertySetExtensionsT
+ {
+ };
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.idl b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.idl
new file mode 100644
index 0000000000..278b3c896c
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.idl
@@ -0,0 +1,8 @@
+namespace SkiaSharp.Views.WinUI.Native
+{
+ static runtimeclass PropertySetExtensions
+ {
+ static void AddSingle(Windows.Foundation.Collections.PropertySet propertySet, String key, Single value);
+ static void AddSize(Windows.Foundation.Collections.PropertySet propertySet, String key, Windows.Foundation.Size value);
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj
new file mode 100644
index 0000000000..978dfa70aa
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+ true
+ true
+ true
+ {730af4c9-82d2-4fa7-aa32-154f3524ebd2}
+ SkiaSharp.Views.WinUI.Native
+ SkiaSharp.Views.WinUI.Native
+ en-US
+ 16.0
+ false
+ Windows Store
+ 10.0
+ 10.0.22621.0
+ 10.0.17763.0
+ true
+ true
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+ Release
+ ARM64
+
+
+
+ DynamicLibrary
+ v143
+ Unicode
+ false
+ true
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ SkiaSharp_Views_WinUI_Native.def
+ /DEBUGTYPE:CV,FIXUP
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+
+ PropertySetExtensions.cpp
+
+
+ BufferExtensions.cpp
+
+
+
+
+ Create
+
+
+
+
+
+
+
+ Code
+ PropertySetExtensions.cpp
+
+
+ Code
+ BufferExtensions.cpp
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj.filters b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj.filters
new file mode 100644
index 0000000000..1aacc36f59
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj.filters
@@ -0,0 +1,31 @@
+
+
+
+
+ accd3aa8-1ba0-4223-9bbe-0c431709210b
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {926ab91d-31b4-48c3-b9a4-e681349f27f0}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp_Views_WinUI_Native.def b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp_Views_WinUI_Native.def
new file mode 100644
index 0000000000..24e7c1235c
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp_Views_WinUI_Native.def
@@ -0,0 +1,3 @@
+EXPORTS
+DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/packages.config b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/packages.config
new file mode 100644
index 0000000000..152b1d8ec4
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.cpp b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.cpp
new file mode 100644
index 0000000000..1d9f38c57d
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.h b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.h
new file mode 100644
index 0000000000..00fa52b21d
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.h
@@ -0,0 +1,27 @@
+#pragma once
+#include
+#include
+#include
+#include
+
+// Undefine GetCurrentTime macro to prevent
+// conflict with Storyboard::GetCurrentTime
+#undef GetCurrentTime
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/readme.txt b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/readme.txt
new file mode 100644
index 0000000000..fd4c59a522
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/readme.txt
@@ -0,0 +1,27 @@
+========================================================================
+ SkiaSharp.Views.WinUI.Native Project Overview
+========================================================================
+
+This project demonstrates how to get started authoring Windows Runtime
+classes directly with standard C++, using the Windows App SDK and
+C++/WinRT packages to generate implementation headers from interface
+(IDL) files. The generated Windows Runtime component binary and WinMD
+files should then be bundled with the app consuming them.
+
+Steps:
+1. Create an interface (IDL) file to define your Windows Runtime class,
+ its default interface, and any other interfaces it implements.
+2. Build the project once to generate module.g.cpp, module.h.cpp, and
+ implementation templates under the "Generated Files" folder, as
+ well as skeleton class definitions under "Generated Files\sources".
+3. Use the skeleton class definitions for reference to implement your
+ Windows Runtime classes.
+
+========================================================================
+Learn more about Windows App SDK here:
+https://docs.microsoft.com/windows/apps/windows-app-sdk/
+Learn more about WinUI3 here:
+https://docs.microsoft.com/windows/apps/winui/winui3/
+Learn more about C++/WinRT here:
+http://aka.ms/cppwinrt/
+========================================================================
diff --git a/native/winui/build.cake b/native/winui/build.cake
new file mode 100644
index 0000000000..2c3384bf91
--- /dev/null
+++ b/native/winui/build.cake
@@ -0,0 +1,45 @@
+DirectoryPath ROOT_PATH = MakeAbsolute(Directory("../.."));
+DirectoryPath OUTPUT_PATH = MakeAbsolute(ROOT_PATH.Combine("output/native/winui"));
+
+#load "../../cake/native-shared.cake"
+#load "../../cake/msbuild.cake"
+
+Task("SkiaSharp.Views.WinUI.Native")
+ .WithCriteria(IsRunningOnWindows())
+ .Does(() =>
+{
+ Build("x86", "Win32");
+ Build("x64", "x64");
+ Build("arm64", "arm64");
+
+ void Build(string arch, string nativeArch)
+ {
+ if (Skip(arch)) return;
+
+ RunMSBuild("SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln",
+ restore: false,
+ targets: new[] { "Restore" },
+ properties: new Dictionary {
+ { "RestorePackagesConfig", "true" }
+ });
+ RunMSBuild("SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln", arch);
+
+ var name = "SkiaSharp.Views.WinUI.Native";
+
+ var outDir = OUTPUT_PATH.Combine(arch);
+ EnsureDirectoryExists(outDir);
+ CopyFileToDirectory($"{name}/{name}/bin/{nativeArch}/{CONFIGURATION}/{name}.dll", outDir);
+ CopyFileToDirectory($"{name}/{name}/bin/{nativeArch}/{CONFIGURATION}/{name}.pdb", outDir);
+ CopyFileToDirectory($"{name}/{name}/bin/{nativeArch}/{CONFIGURATION}/{name}.winmd", outDir);
+
+ var anyOutDir = OUTPUT_PATH.Combine("any");
+ EnsureDirectoryExists(anyOutDir);
+ CopyFileToDirectory($"{name}/{name}.Projection/bin/{CONFIGURATION}/net6.0-windows10.0.19041.0/{name}.Projection.dll", anyOutDir);
+ CopyFileToDirectory($"{name}/{name}.Projection/bin/{CONFIGURATION}/net6.0-windows10.0.19041.0/{name}.Projection.pdb", anyOutDir);
+ }
+});
+
+Task("Default")
+ .IsDependentOn("SkiaSharp.Views.WinUI.Native");
+
+RunTarget(TARGET);
diff --git a/nuget/SkiaSharp.NativeAssets.WinUI.nuspec b/nuget/SkiaSharp.NativeAssets.WinUI.nuspec
new file mode 100644
index 0000000000..5c7289c2ee
--- /dev/null
+++ b/nuget/SkiaSharp.NativeAssets.WinUI.nuspec
@@ -0,0 +1,59 @@
+
+
+
+
+
+ SkiaSharp.NativeAssets.WinUI
+ SkiaSharp - Native Assets for WinUI
+ 1.0.0
+
+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.
+
+
+SkiaSharp is a cross-platform 2D graphics API for .NET platforms that can be used across mobile, server and desktop models to render images.
+
+
+Please visit https://go.microsoft.com/fwlink/?linkid=868517 to view the release notes.
+
+ https://go.microsoft.com/fwlink/?linkid=868515
+ https://go.microsoft.com/fwlink/?linkid=2130524
+ xamarin graphics ios android linux windows uwp tvos watchos macos tizen cross-platform skiasharp
+
+
+ MIT
+ Microsoft
+ Microsoft
+ true
+ © Microsoft Corporation. All rights reserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuget/SkiaSharp.Views.WinUI.nuspec b/nuget/SkiaSharp.Views.WinUI.nuspec
index 1129a2b87d..e82438528c 100644
--- a/nuget/SkiaSharp.Views.WinUI.nuspec
+++ b/nuget/SkiaSharp.Views.WinUI.nuspec
@@ -30,10 +30,12 @@ Please visit https://go.microsoft.com/fwlink/?linkid=868517 to view the release
+
+
diff --git a/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj b/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj
index 8f1967ac88..44f0b7f230 100644
--- a/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj
+++ b/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj
@@ -24,6 +24,8 @@
+
+
diff --git a/scripts/azure-pipelines-variables.yml b/scripts/azure-pipelines-variables.yml
index a6bf0df917..bc6f1de9e0 100644
--- a/scripts/azure-pipelines-variables.yml
+++ b/scripts/azure-pipelines-variables.yml
@@ -17,7 +17,7 @@ variables:
XCODE_VERSION: 14.2
VISUAL_STUDIO_VERSION: ''
DOTNET_VERSION_PREVIEW: '7.0.302'
- DOTNET_WORKLOAD_SOURCE: 'https://maui.blob.core.windows.net/metadata/rollbacks/7.0.81.json'
+ DOTNET_WORKLOAD_SOURCE: 'https://github.com/dotnet/maui/releases/download/7.0.81/7.0.81.json'
DOTNET_WORKLOAD_TIZEN: '7.0.111'
CONFIGURATION: 'Release'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
diff --git a/scripts/azure-templates-bootstrapper.yml b/scripts/azure-templates-bootstrapper.yml
index 9a6877222c..b00264b77e 100644
--- a/scripts/azure-templates-bootstrapper.yml
+++ b/scripts/azure-templates-bootstrapper.yml
@@ -85,11 +85,6 @@ jobs:
displayName: Print current SDL input
- template: /scripts/azure-templates-variables.yml@self
- # checkout required skia PR
- - pwsh: .\scripts\checkout-skia.ps1 -GitHubToken $(GitHub.Token.PublicAccess)
- displayName: Checkout required skia PR
- condition: eq(variables['Build.Reason'], 'PullRequest')
-
- ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- template: /scripts/azure-templates-github-status.yml@self
parameters:
diff --git a/scripts/azure-templates-stages.yml b/scripts/azure-templates-stages.yml
index 0e041afc89..d479bb6267 100644
--- a/scripts/azure-templates-stages.yml
+++ b/scripts/azure-templates-stages.yml
@@ -237,6 +237,36 @@ stages:
vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
target: externals-nanoserver
additionalArgs: --buildarch=x64
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native WinUI|x86 (Win)
+ parameters:
+ name: native_winui_x86_windows
+ displayName: WinUI x86
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ target: externals-winui
+ additionalArgs: --buildarch=x86
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native WinUI|x64 (Win)
+ parameters:
+ name: native_winui_x64_windows
+ displayName: WinUI x64
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ target: externals-winui
+ additionalArgs: --buildarch=x64
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native WinUI|arm64 (Win)
+ parameters:
+ name: native_winui_arm64_windows
+ displayName: WinUI arm64
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ target: externals-winui
+ additionalArgs: --buildarch=arm64
- ${{ if ne(parameters.buildPipelineType, 'tests') }}:
- stage: native_macos
@@ -501,6 +531,10 @@ stages:
- name: native_win32_x86_windows
- name: native_win32_x64_windows
- name: native_win32_arm64_windows
+ # WinUI
+ - name: native_winui_x86_windows
+ - name: native_winui_x64_windows
+ - name: native_winui_arm64_windows
# Nano Server
- name: native_win32_x64_nanoserver_windows
# iOS
@@ -648,15 +682,6 @@ stages:
- pwsh: |
Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\nugets-symbols\' -Destination '.\output\'
displayName: Prepare the nugets-symbols artifact for publishing
- - pwsh: |
- $nupkgs = (Get-ChildItem ".\output\nugets*\*.*nupkg")
- foreach ($nupkg in $nupkgs) {
- $filename = $nupkg.Name.TrimEnd('.nupkg')
- $dest = ".\output\extracted_nugets\$filename"
- Write-Host "Extracting '$nupkg' to '$dest'..."
- Expand-Archive $nupkg $dest
- }
- displayName: Extract all the .nupkg files for scanning
- pwsh: |
Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\nugets-special\' -Destination '.\output\'
displayName: Prepare the nugets-special artifact for publishing
@@ -672,6 +697,35 @@ stages:
path: '.\output\nugets-special'
- name: nuget_symbols
path: '.\output\nugets-symbols'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Scan NuGets
+ parameters:
+ name: scanning_windows
+ displayName: Scan NuGets
+ sdl: ${{ parameters.sdl }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
+ dependsOn: package_windows
+ skipInstall: true
+ skipSteps: true
+ shouldPublish: false
+ requiredArtifacts:
+ - name: nuget
+ dir: nugets
+ - name: nuget_special
+ dir: nugets-special
+ - name: nuget_symbols
+ dir: nugets-symbols
+ preBuildSteps:
+ - pwsh: |
+ $nupkgs = (Get-ChildItem ".\output\nugets*\*.*nupkg")
+ foreach ($nupkg in $nupkgs) {
+ $filename = $nupkg.Name.TrimEnd('.nupkg')
+ $dest = ".\output\extracted_nugets\$filename"
+ Write-Host "Extracting '$nupkg' to '$dest'..."
+ Expand-Archive $nupkg $dest
+ Remove-Item $nupkg -Force -ErrorAction Continue
+ }
+ displayName: Extract all the .nupkg files for scanning
- ${{ if ne(parameters.buildPipelineType, 'build') }}:
- stage: api_diff
diff --git a/scripts/install-dotnet-workloads.ps1 b/scripts/install-dotnet-workloads.ps1
index d605a05947..6c64addb7e 100644
--- a/scripts/install-dotnet-workloads.ps1
+++ b/scripts/install-dotnet-workloads.ps1
@@ -24,6 +24,7 @@ Write-Host "Installing .NET workloads..."
--source $feed1 `
--source $feed2 `
--source $feed3 `
+ --verbosity diagnostic `
--skip-sign-check
Write-Host "Installing Tizen workloads..."
diff --git a/source/SkiaSharp.Build.props b/source/SkiaSharp.Build.props
index 0dd4f1925c..d930fed995 100644
--- a/source/SkiaSharp.Build.props
+++ b/source/SkiaSharp.Build.props
@@ -108,6 +108,10 @@
$(DotNetNextVersion);net$(DotNetNextVersion)-windows10.0.19041.0
+
+ net$(DotNetBaseVersion)-windows10.0.18362.0;net$(DotNetBaseVersion)-windows10.0.19041.0
+
+
portable
true
diff --git a/source/SkiaSharp.Build.targets b/source/SkiaSharp.Build.targets
index c3241c6327..5ae8883600 100644
--- a/source/SkiaSharp.Build.targets
+++ b/source/SkiaSharp.Build.targets
@@ -135,6 +135,9 @@ internal partial class VersionConstants {
<_SignAssemblyAfterTargets>
CoreCompile
+ <_SignAssemblyAfterTargets Condition="'$(CsWinRTIncludes)' != ''">
+ CsWinRTReplaceForPatchedRuntime
+
();
- if (byteBuffer == null)
- throw new InvalidCastException("Unable to convert WriteableBitmap.PixelBuffer to IBufferByteAccess.");
-
- return byteBuffer.Buffer;
- }
- }
-}
-
-namespace ABI.SkiaSharp.Views.Windows
-{
- [DynamicInterfaceCastableImplementation]
- [Guid("905a0fef-bc53-11df-8c49-001e4fc686da")]
- internal interface IBufferByteAccess : global::SkiaSharp.Views.Windows.IBufferByteAccess
- {
- public struct VftblPtr
- {
- public IntPtr Vftbl;
- }
-
- [Guid("905a0fef-bc53-11df-8c49-001e4fc686da")]
- public struct Vftbl
- {
- public delegate int GetBufferDelegate(IntPtr thisPtr, out IntPtr buffer);
-
- internal IUnknownVftbl IUnknownVftbl;
- public GetBufferDelegate getBuffer;
-
- static unsafe Vftbl()
- {
- AbiToProjectionVftable = new Vftbl
- {
- IUnknownVftbl = IUnknownVftbl.AbiToProjectionVftbl,
- getBuffer = DoAbiGetBuffer
- };
- var nativeVftbl = (IntPtr*)Marshal.AllocCoTaskMem(Marshal.SizeOf() + sizeof(IntPtr) * 12);
- Marshal.StructureToPtr(AbiToProjectionVftable.IUnknownVftbl, (IntPtr)nativeVftbl, false);
- nativeVftbl[3] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.getBuffer);
- AbiToProjectionVftablePtr = (IntPtr)nativeVftbl;
- }
-
- public static readonly Vftbl AbiToProjectionVftable;
- public static readonly IntPtr AbiToProjectionVftablePtr;
-
- internal unsafe Vftbl(IntPtr ptr)
- {
- var vftblPtr = Marshal.PtrToStructure(ptr);
- var vftbl = (IntPtr*)vftblPtr.Vftbl;
- IUnknownVftbl = Marshal.PtrToStructure(vftblPtr.Vftbl);
- getBuffer = Marshal.GetDelegateForFunctionPointer(vftbl[3]);
- }
-
- private static int DoAbiGetBuffer(IntPtr thisPtr, out IntPtr buffer)
- {
- buffer = default;
- try
- {
- buffer = ComWrappersSupport.FindObject(thisPtr).Buffer;
- }
- catch (Exception ex)
- {
- return Marshal.GetHRForException(ex);
- }
- return 0;
- }
- }
-
- IntPtr global::SkiaSharp.Views.Windows.IBufferByteAccess.Buffer
- {
- get
- {
- var obj = (ObjectReference)((IWinRTObject)this).GetObjectReferenceForType(typeof(global::SkiaSharp.Views.Windows.IBufferByteAccess).TypeHandle);
- var ThisPtr = obj.ThisPtr;
- Marshal.ThrowExceptionForHR(obj.Vftbl.getBuffer(ThisPtr, out IntPtr buffer));
- return buffer;
- }
- }
-
- internal static ObjectReference FromAbi(IntPtr thisPtr) =>
- ObjectReference.FromAbi(thisPtr);
- }
-}
diff --git a/source/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI.csproj b/source/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI.csproj
index 691b4600b3..e7b2392008 100644
--- a/source/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI.csproj
+++ b/source/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI/SkiaSharp.Views.WinUI.csproj
@@ -1,6 +1,6 @@
- net6.0-windows10.0.18362.0;net6.0-windows10.0.19041.0
+ $(WindowsTargetFrameworks)
10.0.17763.0
SkiaSharp.Views.Windows
SkiaSharp.Views.Windows
@@ -20,4 +20,7 @@
+
+
+
\ No newline at end of file
diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.UWP/UWPExtensions.cs b/source/SkiaSharp.Views/SkiaSharp.Views.UWP/UWPExtensions.cs
index 2bacea1490..1615382242 100644
--- a/source/SkiaSharp.Views/SkiaSharp.Views.UWP/UWPExtensions.cs
+++ b/source/SkiaSharp.Views/SkiaSharp.Views.UWP/UWPExtensions.cs
@@ -1,6 +1,10 @@
using System;
using Windows.Foundation;
using Windows.UI;
+#if WINDOWS && !HAS_UNO
+using Windows.Storage.Streams;
+using SkiaSharp.Views.WinUI.Native;
+#endif
#if WINDOWS || WINUI
using Microsoft.UI.Xaml.Media.Imaging;
@@ -171,6 +175,11 @@ public static bool ToSKPixmap(this WriteableBitmap bitmap, SKPixmap pixmap)
internal static IntPtr GetPixels(this WriteableBitmap bitmap) =>
bitmap.PixelBuffer.GetByteBuffer();
+
+#if WINDOWS
+ internal static IntPtr GetByteBuffer(this IBuffer buffer) =>
+ (IntPtr)BufferExtensions.GetByteBuffer(buffer);
+#endif
#endif
}
}