From 6e6bc030bd2c684dd9bb0ced672e41b9b530ec6e Mon Sep 17 00:00:00 2001 From: Shaojun Li Date: Wed, 15 Jan 2025 17:15:26 +0800 Subject: [PATCH] Add RuntimeShader Support. --- .../ResourcesApi.generated.cs | 1 + .../SceneGraphApi.generated.cs | 1 + .../SkiaSharp.Skottie/SkottieApi.generated.cs | 1 + binding/SkiaSharp/SKImageFilter.cs | 44 +++++++++++++- binding/SkiaSharp/SKRuntimeEffect.cs | 33 +++++++++++ binding/SkiaSharp/SkiaApi.generated.cs | 58 +++++++++++++++++++ 6 files changed, 137 insertions(+), 1 deletion(-) diff --git a/binding/SkiaSharp.Resources/ResourcesApi.generated.cs b/binding/SkiaSharp.Resources/ResourcesApi.generated.cs index 7a98213520..0dba2ca23e 100644 --- a/binding/SkiaSharp.Resources/ResourcesApi.generated.cs +++ b/binding/SkiaSharp.Resources/ResourcesApi.generated.cs @@ -63,6 +63,7 @@ using sk_rrect_t = System.IntPtr; using sk_rtree_factory_t = System.IntPtr; using sk_runtimeeffect_t = System.IntPtr; +using sk_runtimeshaderbuilder_t = System.IntPtr; using sk_shader_t = System.IntPtr; using sk_stream_asset_t = System.IntPtr; using sk_stream_filestream_t = System.IntPtr; diff --git a/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs b/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs index 6ddb553ba7..f2f11ee4c6 100644 --- a/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs +++ b/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs @@ -63,6 +63,7 @@ using sk_rrect_t = System.IntPtr; using sk_rtree_factory_t = System.IntPtr; using sk_runtimeeffect_t = System.IntPtr; +using sk_runtimeshaderbuilder_t = System.IntPtr; using sk_shader_t = System.IntPtr; using sk_stream_asset_t = System.IntPtr; using sk_stream_filestream_t = System.IntPtr; diff --git a/binding/SkiaSharp.Skottie/SkottieApi.generated.cs b/binding/SkiaSharp.Skottie/SkottieApi.generated.cs index 548ed1a044..d8a5a0c857 100644 --- a/binding/SkiaSharp.Skottie/SkottieApi.generated.cs +++ b/binding/SkiaSharp.Skottie/SkottieApi.generated.cs @@ -63,6 +63,7 @@ using sk_rrect_t = System.IntPtr; using sk_rtree_factory_t = System.IntPtr; using sk_runtimeeffect_t = System.IntPtr; +using sk_runtimeshaderbuilder_t = System.IntPtr; using sk_shader_t = System.IntPtr; using sk_stream_asset_t = System.IntPtr; using sk_stream_filestream_t = System.IntPtr; diff --git a/binding/SkiaSharp/SKImageFilter.cs b/binding/SkiaSharp/SKImageFilter.cs index 45eea572e3..2574e077f7 100644 --- a/binding/SkiaSharp/SKImageFilter.cs +++ b/binding/SkiaSharp/SKImageFilter.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; namespace SkiaSharp { @@ -437,7 +438,48 @@ public static SKImageFilter CreateShader (SKShader? shader, bool dither, SKRect private static SKImageFilter CreateShader (SKShader? shader, bool dither, SKRect* cropRect) => GetObject (SkiaApi.sk_imagefilter_new_shader (shader?.Handle ?? IntPtr.Zero, dither, cropRect)); - // + // CreateRuntimeShader + public static SKImageFilter CreateRuntimeShader (SKRuntimeShaderBuilder builder, string childShaderName, SKImageFilter? input) => + CreateRuntimeShader (builder, 0f, childShaderName, input); + + public static SKImageFilter CreateRuntimeShader (SKRuntimeShaderBuilder builder, float maxSampleRadius, string childShaderName, SKImageFilter? input) => + CreateRuntimeShader (builder, maxSampleRadius, [childShaderName], [input]); + + public static SKImageFilter CreateRuntimeShader (SKRuntimeShaderBuilder builder, float maxSampleRadius, string[] childShaderNames, SKImageFilter?[] inputs) + { + SKImageFilter result; + IntPtr runtimeShaderBuilder; + + using var childrenHandles = Utils.RentHandlesArray (builder.Children.ToArray (), true); + fixed (IntPtr* childrenHandlesPtr = childrenHandles) { + runtimeShaderBuilder = SkiaApi.sk_runtimeshaderbuilder_new (builder.Effect.Handle, builder.Uniforms.ToData ().Handle, childrenHandlesPtr, (IntPtr)builder.Children.Count); + } + + using var inputsHandles = Utils.RentHandlesArray (inputs, true); + using var childShaderNamesHandles = Utils.RentArray (inputs.Length, true); + var gcHandles = new GCHandle[childShaderNames.Length]; + + try { + for (int i = 0; i < childShaderNames.Length; i++) { + var handle = GCHandle.Alloc (StringUtilities.GetEncodedText (childShaderNames[i], SKTextEncoding.Utf8), GCHandleType.Pinned); + childShaderNamesHandles[i] = handle.AddrOfPinnedObject (); + } + + fixed (IntPtr* inputsHandlesPtr = inputsHandles) { + fixed (IntPtr* childShaderNamesHandlesPtr = childShaderNamesHandles) { + result = GetObject (SkiaApi.sk_imagefilter_new_runtime_shader (runtimeShaderBuilder, maxSampleRadius, (void**)childShaderNamesHandlesPtr, inputsHandlesPtr, childShaderNames.Length)); + } + } + } finally { + SkiaApi.sk_runtimeshaderbuilder_destructor (runtimeShaderBuilder); + foreach (var handle in gcHandles) { + if (handle.IsAllocated) { + handle.Free (); + } + } + } + return result; + } internal static SKImageFilter GetObject (IntPtr handle) => GetOrAddObject (handle, (h, o) => new SKImageFilter (h, o)); diff --git a/binding/SkiaSharp/SKRuntimeEffect.cs b/binding/SkiaSharp/SKRuntimeEffect.cs index 9a26537938..8817aa279d 100644 --- a/binding/SkiaSharp/SKRuntimeEffect.cs +++ b/binding/SkiaSharp/SKRuntimeEffect.cs @@ -263,6 +263,20 @@ public SKRuntimeEffectUniforms (SKRuntimeEffect effect) } } + public SKRuntimeEffectUniforms (SKRuntimeEffectUniforms effectUniforms) + { + names = effectUniforms.names.ToArray (); + uniforms = effectUniforms.uniforms.ToDictionary (e => e.Key, e => e.Value); + + var dataSize = effectUniforms.data.Size; + if (dataSize > 0) { + data = SKData.CreateCopy (effectUniforms.data.Data, effectUniforms.data.Size); + } else { + data = SKData.Empty; + } + + } + public IReadOnlyList Names => names; @@ -375,6 +389,12 @@ public SKRuntimeEffectChildren (SKRuntimeEffect effect) children = new SKObject[names.Length]; } + public SKRuntimeEffectChildren (SKRuntimeEffectChildren effectChildren) + { + names = effectChildren.names.ToArray (); + children = effectChildren.children.ToArray (); + } + public IReadOnlyList Names => names; @@ -640,6 +660,14 @@ public SKRuntimeEffectBuilder (SKRuntimeEffect effect) Children = new SKRuntimeEffectChildren (effect); } + public SKRuntimeEffectBuilder (SKRuntimeEffectBuilder builder) + { + Effect = builder.Effect; + + Uniforms = new SKRuntimeEffectUniforms (builder.Uniforms); + Children = new SKRuntimeEffectChildren (builder.Children); + } + public SKRuntimeEffect Effect { get; } public SKRuntimeEffectUniforms Uniforms { get; } @@ -661,6 +689,11 @@ public SKRuntimeShaderBuilder (SKRuntimeEffect effect) { } + public SKRuntimeShaderBuilder (SKRuntimeShaderBuilder builder) + : base (builder) + { + } + public SKShader Build () => Effect.ToShader (Uniforms, Children); diff --git a/binding/SkiaSharp/SkiaApi.generated.cs b/binding/SkiaSharp/SkiaApi.generated.cs index 4f038f0077..ed75e059a4 100644 --- a/binding/SkiaSharp/SkiaApi.generated.cs +++ b/binding/SkiaSharp/SkiaApi.generated.cs @@ -62,6 +62,7 @@ using sk_rrect_t = System.IntPtr; using sk_rtree_factory_t = System.IntPtr; using sk_runtimeeffect_t = System.IntPtr; +using sk_runtimeshaderbuilder_t = System.IntPtr; using sk_shader_t = System.IntPtr; using sk_stream_asset_t = System.IntPtr; using sk_stream_filestream_t = System.IntPtr; @@ -7785,6 +7786,25 @@ internal static sk_imagefilter_t sk_imagefilter_new_point_lit_specular (SKPoint3 (sk_imagefilter_new_point_lit_specular_delegate ??= GetSymbol ("sk_imagefilter_new_point_lit_specular")).Invoke (location, lightColor, surfaceScale, ks, shininess, input, cropRect); #endif + // sk_imagefilter_t* sk_imagefilter_new_runtime_shader(const sk_runtimeshaderbuilder_t* builder, float maxSampleRadius, const char*[-1] childShaderNames, const sk_imagefilter_t*[-1] inputs, int inputCount) + #if !USE_DELEGATES + #if USE_LIBRARY_IMPORT + [LibraryImport (SKIA)] + internal static partial sk_imagefilter_t sk_imagefilter_new_runtime_shader (sk_runtimeshaderbuilder_t builder, Single maxSampleRadius, /* char */ void** childShaderNames, sk_imagefilter_t* inputs, Int32 inputCount); + #else // !USE_LIBRARY_IMPORT + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern sk_imagefilter_t sk_imagefilter_new_runtime_shader (sk_runtimeshaderbuilder_t builder, Single maxSampleRadius, /* char */ void** childShaderNames, sk_imagefilter_t* inputs, Int32 inputCount); + #endif + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate sk_imagefilter_t sk_imagefilter_new_runtime_shader (sk_runtimeshaderbuilder_t builder, Single maxSampleRadius, /* char */ void** childShaderNames, sk_imagefilter_t* inputs, Int32 inputCount); + } + private static Delegates.sk_imagefilter_new_runtime_shader sk_imagefilter_new_runtime_shader_delegate; + internal static sk_imagefilter_t sk_imagefilter_new_runtime_shader (sk_runtimeshaderbuilder_t builder, Single maxSampleRadius, /* char */ void** childShaderNames, sk_imagefilter_t* inputs, Int32 inputCount) => + (sk_imagefilter_new_runtime_shader_delegate ??= GetSymbol ("sk_imagefilter_new_runtime_shader")).Invoke (builder, maxSampleRadius, childShaderNames, inputs, inputCount); + #endif + // sk_imagefilter_t* sk_imagefilter_new_shader(const sk_shader_t* shader, bool dither, const sk_rect_t* cropRect) #if !USE_DELEGATES #if USE_LIBRARY_IMPORT @@ -13282,6 +13302,44 @@ internal static void sk_runtimeeffect_unref (sk_runtimeeffect_t effect) => (sk_runtimeeffect_unref_delegate ??= GetSymbol ("sk_runtimeeffect_unref")).Invoke (effect); #endif + // void sk_runtimeshaderbuilder_destructor(sk_runtimeshaderbuilder_t* builder) + #if !USE_DELEGATES + #if USE_LIBRARY_IMPORT + [LibraryImport (SKIA)] + internal static partial void sk_runtimeshaderbuilder_destructor (sk_runtimeshaderbuilder_t builder); + #else // !USE_LIBRARY_IMPORT + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern void sk_runtimeshaderbuilder_destructor (sk_runtimeshaderbuilder_t builder); + #endif + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate void sk_runtimeshaderbuilder_destructor (sk_runtimeshaderbuilder_t builder); + } + private static Delegates.sk_runtimeshaderbuilder_destructor sk_runtimeshaderbuilder_destructor_delegate; + internal static void sk_runtimeshaderbuilder_destructor (sk_runtimeshaderbuilder_t builder) => + (sk_runtimeshaderbuilder_destructor_delegate ??= GetSymbol ("sk_runtimeshaderbuilder_destructor")).Invoke (builder); + #endif + + // sk_runtimeshaderbuilder_t* sk_runtimeshaderbuilder_new(const sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount) + #if !USE_DELEGATES + #if USE_LIBRARY_IMPORT + [LibraryImport (SKIA)] + internal static partial sk_runtimeshaderbuilder_t sk_runtimeshaderbuilder_new (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount); + #else // !USE_LIBRARY_IMPORT + [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] + internal static extern sk_runtimeshaderbuilder_t sk_runtimeshaderbuilder_new (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount); + #endif + #else + private partial class Delegates { + [UnmanagedFunctionPointer (CallingConvention.Cdecl)] + internal delegate sk_runtimeshaderbuilder_t sk_runtimeshaderbuilder_new (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount); + } + private static Delegates.sk_runtimeshaderbuilder_new sk_runtimeshaderbuilder_new_delegate; + internal static sk_runtimeshaderbuilder_t sk_runtimeshaderbuilder_new (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount) => + (sk_runtimeshaderbuilder_new_delegate ??= GetSymbol ("sk_runtimeshaderbuilder_new")).Invoke (effect, uniforms, children, childCount); + #endif + #endregion #region sk_shader.h