diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ca259aa4..823ec27c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -31,6 +31,6 @@ Changed: **PR Checklist** - [ ] Has tests (if omitted, state reason in description) -- [ ] Rebased on top of master at time of PR +- [ ] Rebased on top of main at time of PR - [ ] Changes adhere to coding standard - [ ] Updated documentation diff --git a/README.md b/README.md index b99c6546..aa6e76e1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![SkiaSharp](https://img.shields.io/nuget/vpre/SkiaSharp.svg?maxAge=2592000&label=SkiaSharp%20nuget)](https://www.nuget.org/packages/SkiaSharp) [![SkiaSharp.Views](https://img.shields.io/nuget/vpre/SkiaSharp.Views.svg?maxAge=2592000&label=SkiaSharp.Views%20nuget)](https://www.nuget.org/packages/SkiaSharp.Views) [![SkiaSharp.Views.Forms](https://img.shields.io/nuget/vpre/SkiaSharp.Views.Forms.svg?maxAge=2592000&label=SkiaSharp.Views.Forms%20nuget)](https://www.nuget.org/packages/SkiaSharp.Views.Forms) [![HarfBuzzSharp](https://img.shields.io/nuget/vpre/HarfBuzzSharp.svg?maxAge=2592000&label=HarfBuzzSharp%20nuget)](https://www.nuget.org/packages/HarfBuzzSharp) [![SkiaSharp.Views.Uno](https://img.shields.io/nuget/vpre/SkiaSharp.Views.Uno.svg?maxAge=2592000&label=SkiaSharp.Views.Uno%20nuget)](https://www.nuget.org/packages/SkiaSharp.Views.Uno) [![chat](https://img.shields.io/badge/chat-xamarin%2FXamarinComponents-E60256.svg)](https://gitter.im/xamarin/XamarinComponents) [![SkiaSharp API Docs](https://img.shields.io/badge/docs-skiasharp-1faece.svg)](https://docs.microsoft.com/dotnet/api/SkiaSharp) [![HarfBuzzSharp API Docs](https://img.shields.io/badge/docs-harfbuzzsharp-1faece.svg)](https://docs.microsoft.com/dotnet/api/SkiaSharp) [![SkiaSharp Guides](https://img.shields.io/badge/docs-guides-1faece.svg)](https://docs.microsoft.com/xamarin/graphics-games/skiasharp/) -[![Build Status](https://dev.azure.com/devdiv/DevDiv/_apis/build/status/Xamarin/Components/SkiaSharp?branchName=master)](https://dev.azure.com/devdiv/DevDiv/_build/latest?definitionId=10789&branchName=master) [![Build Status](https://dev.azure.com/xamarin/public/_apis/build/status/mono/SkiaSharp/SkiaSharp%20(Public)?branchName=master)](https://dev.azure.com/xamarin/public/_build/latest?definitionId=4&branchName=master) +[![Build Status](https://dev.azure.com/devdiv/DevDiv/_apis/build/status/Xamarin/Components/SkiaSharp?branchName=main)](https://dev.azure.com/devdiv/DevDiv/_build/latest?definitionId=10789&branchName=main) [![Build Status](https://dev.azure.com/xamarin/public/_apis/build/status/mono/SkiaSharp/SkiaSharp%20(Public)?branchName=main)](https://dev.azure.com/xamarin/public/_build/latest?definitionId=4&branchName=main) SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library ([skia.org](https://skia.org/)). It provides a comprehensive 2D API that can diff --git a/binding/Binding.Shared/HashCode.cs b/binding/Binding.Shared/HashCode.cs index 77644ba1..5ebbedea 100644 --- a/binding/Binding.Shared/HashCode.cs +++ b/binding/Binding.Shared/HashCode.cs @@ -1,5 +1,5 @@ // Partial code copied from: -// https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/HashCode.cs +// https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/System.Private.CoreLib/src/System/HashCode.cs using System; using System.Runtime.CompilerServices; diff --git a/binding/Binding/GRContext.cs b/binding/Binding/GRContext.cs index 4048330b..78eff2b3 100644 --- a/binding/Binding/GRContext.cs +++ b/binding/Binding/GRContext.cs @@ -54,33 +54,64 @@ namespace SkiaSharp // CreateGl public static GRContext CreateGl () => - CreateGl (null); + CreateGl (null, null); public static GRContext CreateGl (GRGlInterface backendContext) => - GetObject (SkiaApi.gr_direct_context_make_gl (backendContext == null ? IntPtr.Zero : backendContext.Handle)); + CreateGl (backendContext, null); + + public static GRContext CreateGl (GRContextOptions options) => + CreateGl (null, options); + + public static GRContext CreateGl (GRGlInterface backendContext, GRContextOptions options) + { + var ctx = backendContext == null ? IntPtr.Zero : backendContext.Handle; + + if (options == null) { + return GetObject (SkiaApi.gr_direct_context_make_gl (ctx)); + } else { + var opts = options.ToNative (); + return GetObject (SkiaApi.gr_direct_context_make_gl_with_options (ctx, &opts)); + } + } // CreateVulkan - public static GRContext CreateVulkan (GRVkBackendContext backendContext) + public static GRContext CreateVulkan (GRVkBackendContext backendContext) => + CreateVulkan (backendContext, null); + + public static GRContext CreateVulkan (GRVkBackendContext backendContext, GRContextOptions options) { if (backendContext == null) throw new ArgumentNullException (nameof (backendContext)); - return GetObject (SkiaApi.gr_direct_context_make_vulkan (backendContext.ToNative ())); + if (options == null) { + return GetObject (SkiaApi.gr_direct_context_make_vulkan (backendContext.ToNative ())); + } else { + var opts = options.ToNative (); + return GetObject (SkiaApi.gr_direct_context_make_vulkan_with_options (backendContext.ToNative (), &opts)); + } } #if __IOS__ || __MACOS__ // CreateMetal - public static GRContext CreateMetal (Metal.IMTLDevice device, Metal.IMTLCommandQueue queue) + public static GRContext CreateMetal (Metal.IMTLDevice device, Metal.IMTLCommandQueue queue) => + CreateMetal (device, queue, null); + + public static GRContext CreateMetal (Metal.IMTLDevice device, Metal.IMTLCommandQueue queue, GRContextOptions options) { if (device == null) throw new ArgumentNullException (nameof (device)); if (queue == null) throw new ArgumentNullException (nameof (queue)); - return GetObject (SkiaApi.gr_direct_context_make_metal ((void*)device.Handle, (void*)queue.Handle)); + if (options == null) { + return GetObject (SkiaApi.gr_direct_context_make_metal ((void*)device.Handle, (void*)queue.Handle)); + } else { + var opts = options.ToNative (); + return GetObject (SkiaApi.gr_direct_context_make_metal_with_options ((void*)device.Handle, (void*)queue.Handle, &opts)); + } } #endif diff --git a/binding/Binding/GRContextOptions.cs b/binding/Binding/GRContextOptions.cs new file mode 100644 index 00000000..bc3d4269 --- /dev/null +++ b/binding/Binding/GRContextOptions.cs @@ -0,0 +1,29 @@ +using System; + +namespace SkiaSharp +{ + public unsafe class GRContextOptions + { + public bool AvoidStencilBuffers { get; set; } = false; + + public int RuntimeProgramCacheSize { get; set; } = 256; + + public int GlyphCacheTextureMaximumBytes { get; set; } = 2048 * 1024 * 4; + + public bool AllowPathMaskCaching { get; set; } = true; + + public bool DoManualMipmapping { get; set; } = false; + + public int BufferMapThreshold { get; set; } = -1; + + internal GRContextOptionsNative ToNative () => + new GRContextOptionsNative { + fAllowPathMaskCaching = AllowPathMaskCaching ? (byte)1 : (byte)0, + fAvoidStencilBuffers = AvoidStencilBuffers ? (byte)1 : (byte)0, + fBufferMapThreshold = BufferMapThreshold, + fDoManualMipmapping = DoManualMipmapping ? (byte)1 : (byte)0, + fGlyphCacheTextureMaximumBytes = (IntPtr)GlyphCacheTextureMaximumBytes, + fRuntimeProgramCacheSize = RuntimeProgramCacheSize, + }; + } +} diff --git a/binding/Binding/SkiaApi.generated.cs b/binding/Binding/SkiaApi.generated.cs index 9c57d7df..b174d4e8 100644 --- a/binding/Binding/SkiaApi.generated.cs +++ b/binding/Binding/SkiaApi.generated.cs @@ -524,6 +524,20 @@ namespace SkiaSharp (gr_direct_context_make_gl_delegate ??= GetSymbol ("gr_direct_context_make_gl")).Invoke (glInterface); #endif + // gr_direct_context_t* gr_direct_context_make_gl_with_options(const gr_glinterface_t* glInterface, const gr_context_options_t* options) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_direct_context_t gr_direct_context_make_gl_with_options (gr_glinterface_t glInterface, GRContextOptionsNative* options); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_direct_context_t gr_direct_context_make_gl_with_options (gr_glinterface_t glInterface, GRContextOptionsNative* options); + } + private static Delegates.gr_direct_context_make_gl_with_options gr_direct_context_make_gl_with_options_delegate; + internal static gr_direct_context_t gr_direct_context_make_gl_with_options (gr_glinterface_t glInterface, GRContextOptionsNative* options) => + (gr_direct_context_make_gl_with_options_delegate ??= GetSymbol ("gr_direct_context_make_gl_with_options")).Invoke (glInterface, options); + #endif + // gr_direct_context_t* gr_direct_context_make_metal(void* device, void* queue) #if !USE_DELEGATES [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -538,6 +552,20 @@ namespace SkiaSharp (gr_direct_context_make_metal_delegate ??= GetSymbol ("gr_direct_context_make_metal")).Invoke (device, queue); #endif + // gr_direct_context_t* gr_direct_context_make_metal_with_options(void* device, void* queue, const gr_context_options_t* options) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_direct_context_t gr_direct_context_make_metal_with_options (void* device, void* queue, GRContextOptionsNative* options); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_direct_context_t gr_direct_context_make_metal_with_options (void* device, void* queue, GRContextOptionsNative* options); + } + private static Delegates.gr_direct_context_make_metal_with_options gr_direct_context_make_metal_with_options_delegate; + internal static gr_direct_context_t gr_direct_context_make_metal_with_options (void* device, void* queue, GRContextOptionsNative* options) => + (gr_direct_context_make_metal_with_options_delegate ??= GetSymbol ("gr_direct_context_make_metal_with_options")).Invoke (device, queue, options); + #endif + // gr_direct_context_t* gr_direct_context_make_vulkan(const gr_vk_backendcontext_t vkBackendContext) #if !USE_DELEGATES [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -552,6 +580,20 @@ namespace SkiaSharp (gr_direct_context_make_vulkan_delegate ??= GetSymbol ("gr_direct_context_make_vulkan")).Invoke (vkBackendContext); #endif + // gr_direct_context_t* gr_direct_context_make_vulkan_with_options(const gr_vk_backendcontext_t vkBackendContext, const gr_context_options_t* options) + #if !USE_DELEGATES + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern gr_direct_context_t gr_direct_context_make_vulkan_with_options (GRVkBackendContextNative vkBackendContext, GRContextOptionsNative* options); + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate gr_direct_context_t gr_direct_context_make_vulkan_with_options (GRVkBackendContextNative vkBackendContext, GRContextOptionsNative* options); + } + private static Delegates.gr_direct_context_make_vulkan_with_options gr_direct_context_make_vulkan_with_options_delegate; + internal static gr_direct_context_t gr_direct_context_make_vulkan_with_options (GRVkBackendContextNative vkBackendContext, GRContextOptionsNative* options) => + (gr_direct_context_make_vulkan_with_options_delegate ??= GetSymbol ("gr_direct_context_make_vulkan_with_options")).Invoke (vkBackendContext, options); + #endif + // void gr_direct_context_perform_deferred_cleanup(gr_direct_context_t* context, long long ms) #if !USE_DELEGATES [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -13337,6 +13379,53 @@ namespace SkiaSharp #region Structs + // gr_context_options_t + [StructLayout (LayoutKind.Sequential)] + internal unsafe partial struct GRContextOptionsNative : IEquatable { + // public bool fAvoidStencilBuffers + public Byte fAvoidStencilBuffers; + + // public int fRuntimeProgramCacheSize + public Int32 fRuntimeProgramCacheSize; + + // public size_t fGlyphCacheTextureMaximumBytes + public /* size_t */ IntPtr fGlyphCacheTextureMaximumBytes; + + // public bool fAllowPathMaskCaching + public Byte fAllowPathMaskCaching; + + // public bool fDoManualMipmapping + public Byte fDoManualMipmapping; + + // public int fBufferMapThreshold + public Int32 fBufferMapThreshold; + + public readonly bool Equals (GRContextOptionsNative obj) => + fAvoidStencilBuffers == obj.fAvoidStencilBuffers && fRuntimeProgramCacheSize == obj.fRuntimeProgramCacheSize && fGlyphCacheTextureMaximumBytes == obj.fGlyphCacheTextureMaximumBytes && fAllowPathMaskCaching == obj.fAllowPathMaskCaching && fDoManualMipmapping == obj.fDoManualMipmapping && fBufferMapThreshold == obj.fBufferMapThreshold; + + public readonly override bool Equals (object obj) => + obj is GRContextOptionsNative f && Equals (f); + + public static bool operator == (GRContextOptionsNative left, GRContextOptionsNative right) => + left.Equals (right); + + public static bool operator != (GRContextOptionsNative left, GRContextOptionsNative right) => + !left.Equals (right); + + public readonly override int GetHashCode () + { + var hash = new HashCode (); + hash.Add (fAvoidStencilBuffers); + hash.Add (fRuntimeProgramCacheSize); + hash.Add (fGlyphCacheTextureMaximumBytes); + hash.Add (fAllowPathMaskCaching); + hash.Add (fDoManualMipmapping); + hash.Add (fBufferMapThreshold); + return hash.ToHashCode (); + } + + } + // gr_gl_framebufferinfo_t [StructLayout (LayoutKind.Sequential)] public unsafe partial struct GRGlFramebufferInfo : IEquatable { diff --git a/binding/libSkiaSharp.json b/binding/libSkiaSharp.json index 57543655..45c9f828 100644 --- a/binding/libSkiaSharp.json +++ b/binding/libSkiaSharp.json @@ -74,6 +74,10 @@ "cs": "GRMetalTextureInfoNative", "internal": true }, + "gr_context_options_t": { + "cs": "GRContextOptionsNative", + "internal": true + }, "sk_color4f_t": { "cs": "SKColorF", "readonly": true, diff --git a/cake/UtilsManaged.cake b/cake/UtilsManaged.cake index f1893d47..086d9281 100644 --- a/cake/UtilsManaged.cake +++ b/cake/UtilsManaged.cake @@ -250,7 +250,7 @@ string GetDownloadUrl(string id) else if (!string.IsNullOrEmpty (GIT_BRANCH_NAME)) version += "branch." + GIT_BRANCH_NAME.Replace ("/", ".").ToLower (); else - version += "branch.master"; + version += "branch.main"; return string.Format (PREVIEW_FEED_URL, id.ToLower(), version); } diff --git a/externals/skia b/externals/skia index cf307d5c..cecf0b0c 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit cf307d5c463960e0e85630b422e5cec0105c1e39 +Subproject commit cecf0b0ccf451b67e67695ec2c5031eb3ea52028 diff --git a/scripts/azure-pipelines.yml b/scripts/azure-pipelines.yml index 8abf47a6..18bfab01 100644 --- a/scripts/azure-pipelines.yml +++ b/scripts/azure-pipelines.yml @@ -1,11 +1,11 @@ trigger: - - master + - main - develop - patch/* - refs/tags/* pr: - - master + - main - develop - patch/* @@ -684,7 +684,7 @@ stages: parameters: name: native_checks_windows displayName: Run Code Checks - condition: and(always(), eq('refs/heads/master', variables['Build.SourceBranch'])) + condition: and(always(), eq('refs/heads/main', variables['Build.SourceBranch'])) vmImage: $(VM_IMAGE_WINDOWS_PREVIOUS) target: git-sync-deps installWindowsSdk: false @@ -731,7 +731,7 @@ stages: tsaVersion: 'TsaV2' codebase: 'NewOrUpdate' tsaEnvironment: 'PROD' - codeBaseName: 'SkiaSharp_master' + codeBaseName: 'SkiaSharp_main' notificationAlias: 'xamacomd@microsoft.com' notifyAlwaysV2: false instanceUrlForTsaV2: 'DEVDIV' diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs b/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs index 65f1e8fd..f09579e9 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs @@ -51,7 +51,7 @@ namespace SkiaSharp.Views.WPF if (designMode) return; - if (Visibility != Visibility.Visible) + if (Visibility != Visibility.Visible || PresentationSource.FromVisual(this) == null) return; var size = CreateSize(out var scaleX, out var scaleY); diff --git a/tests/Tests/GRContextTest.cs b/tests/Tests/GRContextTest.cs index 2241f1e1..64504299 100644 --- a/tests/Tests/GRContextTest.cs +++ b/tests/Tests/GRContextTest.cs @@ -19,6 +19,19 @@ namespace SkiaSharp.Tests } } + [Trait(CategoryKey, GpuCategory)] + [SkippableFact] + public void CreateDefaultContextWithOptionsIsValid() + { + using var ctx = CreateGlContext(); + ctx.MakeCurrent(); + + var options = new GRContextOptions(); + var grContext = GRContext.CreateGl(options); + + Assert.NotNull(grContext); + } + [Obsolete] [SkippableFact] public void ToGlSizedFormat() @@ -51,6 +64,23 @@ namespace SkiaSharp.Tests } } + [Trait(CategoryKey, GpuCategory)] + [SkippableFact] + public void CreateSpecificContextWithOptionsIsValid() + { + using var ctx = CreateGlContext(); + ctx.MakeCurrent(); + + var glInterface = GRGlInterface.Create(); + + Assert.True(glInterface.Validate()); + + var options = new GRContextOptions(); + var grContext = GRContext.CreateGl(glInterface, options); + + Assert.NotNull(grContext); + } + [Trait(CategoryKey, GpuCategory)] [SkippableFact] public void GpuSurfaceIsCreated() diff --git a/tests/VulkanTests/GRContextTest.cs b/tests/VulkanTests/GRContextTest.cs index 7fff245c..baa54a29 100644 --- a/tests/VulkanTests/GRContextTest.cs +++ b/tests/VulkanTests/GRContextTest.cs @@ -27,5 +27,30 @@ namespace SkiaSharp.Vulkan.Tests Assert.NotNull(grContext); } + + [Trait(CategoryKey, GpuCategory)] + [SkippableFact] + public void CreateVkContextWithOptionsIsValid() + { + using var ctx = CreateVkContext(); + + using var grVkBackendContext = new GRVkBackendContext + { + VkInstance = (IntPtr)ctx.Instance.RawHandle.ToUInt64(), + VkPhysicalDevice = (IntPtr)ctx.PhysicalDevice.RawHandle.ToUInt64(), + VkDevice = (IntPtr)ctx.Device.RawHandle.ToUInt64(), + VkQueue = (IntPtr)ctx.GraphicsQueue.RawHandle.ToUInt64(), + GraphicsQueueIndex = ctx.GraphicsFamily, + GetProcedureAddress = ctx.GetProc + }; + + Assert.NotNull(grVkBackendContext); + + var options = new GRContextOptions(); + + using var grContext = GRContext.CreateVulkan(grVkBackendContext, options); + + Assert.NotNull(grContext); + } } }