From 5fdca193dab411cb1f8fd9efda08e74a21fd3ca3 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 27 Apr 2026 04:05:08 +0200 Subject: [PATCH 1/5] Add sk_imagefilter_new_runtime_shader C API functions Add two new C API functions for creating image filters from runtime shaders: - sk_imagefilter_new_runtime_shader: single-child variant - sk_imagefilter_new_runtime_shader_with_children: multi-child with maxSampleRadius Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- include/c/sk_imagefilter.h | 2 ++ src/c/sk_imagefilter.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/c/sk_imagefilter.h b/include/c/sk_imagefilter.h index 528250a4bc79..4a630b620915 100644 --- a/include/c/sk_imagefilter.h +++ b/include/c/sk_imagefilter.h @@ -47,6 +47,8 @@ SK_C_API sk_imagefilter_t* sk_imagefilter_new_spot_lit_diffuse(const sk_point3_t SK_C_API sk_imagefilter_t* sk_imagefilter_new_distant_lit_specular(const sk_point3_t* direction, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect); SK_C_API sk_imagefilter_t* sk_imagefilter_new_point_lit_specular(const sk_point3_t* location, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect); SK_C_API sk_imagefilter_t* sk_imagefilter_new_spot_lit_specular(const sk_point3_t* location, const sk_point3_t* target, float specularExponent, float cutoffAngle, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect); +SK_C_API sk_imagefilter_t* sk_imagefilter_new_runtime_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input); +SK_C_API sk_imagefilter_t* sk_imagefilter_new_runtime_shader_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); SK_C_PLUS_PLUS_END_GUARD diff --git a/src/c/sk_imagefilter.cpp b/src/c/sk_imagefilter.cpp index fe98b1c79e02..b3b56056e53a 100644 --- a/src/c/sk_imagefilter.cpp +++ b/src/c/sk_imagefilter.cpp @@ -12,6 +12,7 @@ #include "include/core/SkPicture.h" #include "include/core/SkRegion.h" #include "include/effects/SkImageFilters.h" +#include "include/effects/SkRuntimeEffect.h" #include "include/c/sk_imagefilter.h" @@ -143,3 +144,36 @@ sk_imagefilter_t* sk_imagefilter_new_point_lit_specular(const sk_point3_t* locat sk_imagefilter_t* sk_imagefilter_new_spot_lit_specular(const sk_point3_t* location, const sk_point3_t* target, float specularExponent, float cutoffAngle, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect) { return ToImageFilter(SkImageFilters::SpotLitSpecular(*AsPoint3(location), *AsPoint3(target), specularExponent, cutoffAngle, lightColor, surfaceScale, ks, shininess, sk_ref_sp(AsImageFilter(input)), AsRect(cropRect)).release()); } + +sk_imagefilter_t* sk_imagefilter_new_runtime_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input) { + SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); + + auto effectChildren = AsRuntimeEffect(effect)->children(); + for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { + builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); + } + + std::string_view name = childShaderName ? std::string_view(childShaderName) : std::string_view(); + return ToImageFilter(SkImageFilters::RuntimeShader(builder, name, sk_ref_sp(AsImageFilter(input))).release()); +} + +sk_imagefilter_t* sk_imagefilter_new_runtime_shader_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { + SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); + + auto effectChildren = AsRuntimeEffect(effect)->children(); + for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { + builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); + } + + std::vector names(inputCount); + for (int i = 0; i < inputCount; i++) { + names[i] = std::string_view(childShaderNames[i]); + } + + std::vector> skInputs(inputCount); + for (int i = 0; i < inputCount; i++) { + skInputs[i] = sk_ref_sp(AsImageFilter(inputs[i])); + } + + return ToImageFilter(SkImageFilters::RuntimeShader(builder, maxSampleRadius, names.data(), skInputs.data(), inputCount).release()); +} From 3a12c1bbe92fff729931b810e88ff60db3e6fb01 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Tue, 5 May 2026 22:16:35 +0200 Subject: [PATCH 2/5] Move runtime shader image filter C API to sk_runtimeeffect Rename and relocate from sk_imagefilter_new_runtime_shader* to sk_runtimeeffect_make_image_filter* to match the existing pattern of sk_runtimeeffect_make_shader/color_filter/blender. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- include/c/sk_imagefilter.h | 2 -- include/c/sk_runtimeeffect.h | 2 ++ src/c/sk_imagefilter.cpp | 33 --------------------------------- src/c/sk_runtimeeffect.cpp | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/include/c/sk_imagefilter.h b/include/c/sk_imagefilter.h index 4a630b620915..528250a4bc79 100644 --- a/include/c/sk_imagefilter.h +++ b/include/c/sk_imagefilter.h @@ -47,8 +47,6 @@ SK_C_API sk_imagefilter_t* sk_imagefilter_new_spot_lit_diffuse(const sk_point3_t SK_C_API sk_imagefilter_t* sk_imagefilter_new_distant_lit_specular(const sk_point3_t* direction, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect); SK_C_API sk_imagefilter_t* sk_imagefilter_new_point_lit_specular(const sk_point3_t* location, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect); SK_C_API sk_imagefilter_t* sk_imagefilter_new_spot_lit_specular(const sk_point3_t* location, const sk_point3_t* target, float specularExponent, float cutoffAngle, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect); -SK_C_API sk_imagefilter_t* sk_imagefilter_new_runtime_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input); -SK_C_API sk_imagefilter_t* sk_imagefilter_new_runtime_shader_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); SK_C_PLUS_PLUS_END_GUARD diff --git a/include/c/sk_runtimeeffect.h b/include/c/sk_runtimeeffect.h index fe56b447f403..21012eb70c0a 100644 --- a/include/c/sk_runtimeeffect.h +++ b/include/c/sk_runtimeeffect.h @@ -19,6 +19,8 @@ SK_C_API void sk_runtimeeffect_unref(sk_runtimeeffect_t* effect); SK_C_API sk_shader_t* sk_runtimeeffect_make_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const sk_matrix_t* localMatrix); SK_C_API sk_colorfilter_t* sk_runtimeeffect_make_color_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); SK_C_API sk_blender_t* sk_runtimeeffect_make_blender(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); SK_C_API size_t sk_runtimeeffect_get_uniform_byte_size(const sk_runtimeeffect_t* effect); SK_C_API size_t sk_runtimeeffect_get_uniforms_size(const sk_runtimeeffect_t* effect); diff --git a/src/c/sk_imagefilter.cpp b/src/c/sk_imagefilter.cpp index b3b56056e53a..b39c1f5d9b52 100644 --- a/src/c/sk_imagefilter.cpp +++ b/src/c/sk_imagefilter.cpp @@ -144,36 +144,3 @@ sk_imagefilter_t* sk_imagefilter_new_point_lit_specular(const sk_point3_t* locat sk_imagefilter_t* sk_imagefilter_new_spot_lit_specular(const sk_point3_t* location, const sk_point3_t* target, float specularExponent, float cutoffAngle, sk_color_t lightColor, float surfaceScale, float ks, float shininess, const sk_imagefilter_t* input, const sk_rect_t* cropRect) { return ToImageFilter(SkImageFilters::SpotLitSpecular(*AsPoint3(location), *AsPoint3(target), specularExponent, cutoffAngle, lightColor, surfaceScale, ks, shininess, sk_ref_sp(AsImageFilter(input)), AsRect(cropRect)).release()); } - -sk_imagefilter_t* sk_imagefilter_new_runtime_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input) { - SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); - - auto effectChildren = AsRuntimeEffect(effect)->children(); - for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { - builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); - } - - std::string_view name = childShaderName ? std::string_view(childShaderName) : std::string_view(); - return ToImageFilter(SkImageFilters::RuntimeShader(builder, name, sk_ref_sp(AsImageFilter(input))).release()); -} - -sk_imagefilter_t* sk_imagefilter_new_runtime_shader_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { - SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); - - auto effectChildren = AsRuntimeEffect(effect)->children(); - for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { - builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); - } - - std::vector names(inputCount); - for (int i = 0; i < inputCount; i++) { - names[i] = std::string_view(childShaderNames[i]); - } - - std::vector> skInputs(inputCount); - for (int i = 0; i < inputCount; i++) { - skInputs[i] = sk_ref_sp(AsImageFilter(inputs[i])); - } - - return ToImageFilter(SkImageFilters::RuntimeShader(builder, maxSampleRadius, names.data(), skInputs.data(), inputCount).release()); -} diff --git a/src/c/sk_runtimeeffect.cpp b/src/c/sk_runtimeeffect.cpp index a700576d6903..bf39c5dc8113 100644 --- a/src/c/sk_runtimeeffect.cpp +++ b/src/c/sk_runtimeeffect.cpp @@ -7,7 +7,9 @@ #include "include/core/SkTypes.h" #include "include/core/SkColorFilter.h" +#include "include/core/SkImageFilter.h" #include "include/core/SkShader.h" +#include "include/effects/SkImageFilters.h" #include "include/effects/SkRuntimeEffect.h" #include "include/c/sk_types.h" @@ -129,3 +131,36 @@ void sk_runtimeeffect_get_child_from_index(const sk_runtimeeffect_t* effect, int void sk_runtimeeffect_get_child_from_name(const sk_runtimeeffect_t* effect, const char* name, size_t len, sk_runtimeeffect_child_t* cchild) { *cchild = *ToRuntimeEffectChild(AsRuntimeEffect(effect)->findChild(std::string_view(name, len))); } + +sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input) { + SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); + + auto effectChildren = AsRuntimeEffect(effect)->children(); + for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { + builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); + } + + std::string_view name = childShaderName ? std::string_view(childShaderName) : std::string_view(); + return ToImageFilter(SkImageFilters::RuntimeShader(builder, name, sk_ref_sp(AsImageFilter(input))).release()); +} + +sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { + SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); + + auto effectChildren = AsRuntimeEffect(effect)->children(); + for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { + builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); + } + + std::vector names(inputCount); + for (int i = 0; i < inputCount; i++) { + names[i] = std::string_view(childShaderNames[i]); + } + + std::vector> skInputs(inputCount); + for (int i = 0; i < inputCount; i++) { + skInputs[i] = sk_ref_sp(AsImageFilter(inputs[i])); + } + + return ToImageFilter(SkImageFilters::RuntimeShader(builder, maxSampleRadius, names.data(), skInputs.data(), inputCount).release()); +} From 7dbb8356e3917b35071576c4e898186b251ddd99 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 6 May 2026 03:46:01 +0200 Subject: [PATCH 3/5] Simplify image filter C API: drop children param, use STArray Remove children/childCount from sk_runtimeeffect_make_image_filter* since these are not used in practice for image filters. Replace std::vector with STArray for stack-backed small allocations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- include/c/sk_runtimeeffect.h | 4 ++-- src/c/sk_runtimeeffect.cpp | 28 +++++++++------------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/include/c/sk_runtimeeffect.h b/include/c/sk_runtimeeffect.h index 21012eb70c0a..759af2633ce2 100644 --- a/include/c/sk_runtimeeffect.h +++ b/include/c/sk_runtimeeffect.h @@ -19,8 +19,8 @@ SK_C_API void sk_runtimeeffect_unref(sk_runtimeeffect_t* effect); SK_C_API sk_shader_t* sk_runtimeeffect_make_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const sk_matrix_t* localMatrix); SK_C_API sk_colorfilter_t* sk_runtimeeffect_make_color_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); SK_C_API sk_blender_t* sk_runtimeeffect_make_blender(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); -SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input); -SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, const char* childShaderName, const sk_imagefilter_t* input); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); SK_C_API size_t sk_runtimeeffect_get_uniform_byte_size(const sk_runtimeeffect_t* effect); SK_C_API size_t sk_runtimeeffect_get_uniforms_size(const sk_runtimeeffect_t* effect); diff --git a/src/c/sk_runtimeeffect.cpp b/src/c/sk_runtimeeffect.cpp index bf39c5dc8113..32bf4107176f 100644 --- a/src/c/sk_runtimeeffect.cpp +++ b/src/c/sk_runtimeeffect.cpp @@ -11,12 +11,15 @@ #include "include/core/SkShader.h" #include "include/effects/SkImageFilters.h" #include "include/effects/SkRuntimeEffect.h" +#include "include/private/base/SkTArray.h" #include "include/c/sk_types.h" #include "include/c/sk_runtimeeffect.h" #include "src/c/sk_types_priv.h" +using namespace skia_private; + sk_runtimeeffect_t* sk_runtimeeffect_make_for_color_filter(sk_string_t* sksl, sk_string_t* error) { auto [effect, errorMessage] = SkRuntimeEffect::MakeForColorFilter(AsString(*sksl)); if (error && errorMessage.size() > 0) @@ -132,34 +135,21 @@ void sk_runtimeeffect_get_child_from_name(const sk_runtimeeffect_t* effect, cons *cchild = *ToRuntimeEffectChild(AsRuntimeEffect(effect)->findChild(std::string_view(name, len))); } -sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input) { +sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, const char* childShaderName, const sk_imagefilter_t* input) { SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); - auto effectChildren = AsRuntimeEffect(effect)->children(); - for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { - builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); - } - std::string_view name = childShaderName ? std::string_view(childShaderName) : std::string_view(); return ToImageFilter(SkImageFilters::RuntimeShader(builder, name, sk_ref_sp(AsImageFilter(input))).release()); } -sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { +sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); - auto effectChildren = AsRuntimeEffect(effect)->children(); - for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { - builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); - } - - std::vector names(inputCount); - for (int i = 0; i < inputCount; i++) { - names[i] = std::string_view(childShaderNames[i]); - } - - std::vector> skInputs(inputCount); + STArray<4, std::string_view> names(inputCount); + STArray<4, sk_sp> skInputs(inputCount); for (int i = 0; i < inputCount; i++) { - skInputs[i] = sk_ref_sp(AsImageFilter(inputs[i])); + names.push_back(std::string_view(childShaderNames[i])); + skInputs.push_back(sk_ref_sp(AsImageFilter(inputs[i]))); } return ToImageFilter(SkImageFilters::RuntimeShader(builder, maxSampleRadius, names.data(), skInputs.data(), inputCount).release()); From 3feed897a132375373e32707104e98b2d93e4be6 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 6 May 2026 04:09:25 +0200 Subject: [PATCH 4/5] Restore children param in image filter C API, keep STArray Children parameter is passed through to the builder for future use with static shader/blender/colorfilter children alongside image filter inputs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- include/c/sk_runtimeeffect.h | 4 ++-- src/c/sk_runtimeeffect.cpp | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/include/c/sk_runtimeeffect.h b/include/c/sk_runtimeeffect.h index 759af2633ce2..21012eb70c0a 100644 --- a/include/c/sk_runtimeeffect.h +++ b/include/c/sk_runtimeeffect.h @@ -19,8 +19,8 @@ SK_C_API void sk_runtimeeffect_unref(sk_runtimeeffect_t* effect); SK_C_API sk_shader_t* sk_runtimeeffect_make_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const sk_matrix_t* localMatrix); SK_C_API sk_colorfilter_t* sk_runtimeeffect_make_color_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); SK_C_API sk_blender_t* sk_runtimeeffect_make_blender(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); -SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, const char* childShaderName, const sk_imagefilter_t* input); -SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); SK_C_API size_t sk_runtimeeffect_get_uniform_byte_size(const sk_runtimeeffect_t* effect); SK_C_API size_t sk_runtimeeffect_get_uniforms_size(const sk_runtimeeffect_t* effect); diff --git a/src/c/sk_runtimeeffect.cpp b/src/c/sk_runtimeeffect.cpp index 32bf4107176f..4ff1c185f60c 100644 --- a/src/c/sk_runtimeeffect.cpp +++ b/src/c/sk_runtimeeffect.cpp @@ -18,8 +18,6 @@ #include "src/c/sk_types_priv.h" -using namespace skia_private; - sk_runtimeeffect_t* sk_runtimeeffect_make_for_color_filter(sk_string_t* sksl, sk_string_t* error) { auto [effect, errorMessage] = SkRuntimeEffect::MakeForColorFilter(AsString(*sksl)); if (error && errorMessage.size() > 0) @@ -135,18 +133,28 @@ void sk_runtimeeffect_get_child_from_name(const sk_runtimeeffect_t* effect, cons *cchild = *ToRuntimeEffectChild(AsRuntimeEffect(effect)->findChild(std::string_view(name, len))); } -sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, const char* childShaderName, const sk_imagefilter_t* input) { +sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input) { SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); + auto effectChildren = AsRuntimeEffect(effect)->children(); + for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { + builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); + } + std::string_view name = childShaderName ? std::string_view(childShaderName) : std::string_view(); return ToImageFilter(SkImageFilters::RuntimeShader(builder, name, sk_ref_sp(AsImageFilter(input))).release()); } -sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { +sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) { SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); - STArray<4, std::string_view> names(inputCount); - STArray<4, sk_sp> skInputs(inputCount); + auto effectChildren = AsRuntimeEffect(effect)->children(); + for (size_t i = 0; i < childCount && i < effectChildren.size(); i++) { + builder.child(effectChildren[i].name) = sk_ref_sp(AsFlattenable(children[i])); + } + + skia_private::STArray<4, std::string_view> names(inputCount); + skia_private::STArray<4, sk_sp> skInputs(inputCount); for (int i = 0; i < inputCount; i++) { names.push_back(std::string_view(childShaderNames[i])); skInputs.push_back(sk_ref_sp(AsImageFilter(inputs[i]))); From b0ad6772638c106d85ba280af56b2b64df380193 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 6 May 2026 04:28:46 +0200 Subject: [PATCH 5/5] Add maxSampleRadius to single-child C API Pass sampleRadius through to C++ RuntimeShader single-child path instead of defaulting to 0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- include/c/sk_runtimeeffect.h | 2 +- src/c/sk_runtimeeffect.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/c/sk_runtimeeffect.h b/include/c/sk_runtimeeffect.h index 21012eb70c0a..ed7091fb0f2a 100644 --- a/include/c/sk_runtimeeffect.h +++ b/include/c/sk_runtimeeffect.h @@ -19,7 +19,7 @@ SK_C_API void sk_runtimeeffect_unref(sk_runtimeeffect_t* effect); SK_C_API sk_shader_t* sk_runtimeeffect_make_shader(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const sk_matrix_t* localMatrix); SK_C_API sk_colorfilter_t* sk_runtimeeffect_make_color_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); SK_C_API sk_blender_t* sk_runtimeeffect_make_blender(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount); -SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input); +SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char* childShaderName, const sk_imagefilter_t* input); SK_C_API sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount); SK_C_API size_t sk_runtimeeffect_get_uniform_byte_size(const sk_runtimeeffect_t* effect); diff --git a/src/c/sk_runtimeeffect.cpp b/src/c/sk_runtimeeffect.cpp index 4ff1c185f60c..695ded746639 100644 --- a/src/c/sk_runtimeeffect.cpp +++ b/src/c/sk_runtimeeffect.cpp @@ -133,7 +133,7 @@ void sk_runtimeeffect_get_child_from_name(const sk_runtimeeffect_t* effect, cons *cchild = *ToRuntimeEffectChild(AsRuntimeEffect(effect)->findChild(std::string_view(name, len))); } -sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, const char* childShaderName, const sk_imagefilter_t* input) { +sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char* childShaderName, const sk_imagefilter_t* input) { SkRuntimeShaderBuilder builder(sk_ref_sp(AsRuntimeEffect(effect)), sk_ref_sp(AsData(uniforms))); auto effectChildren = AsRuntimeEffect(effect)->children(); @@ -142,7 +142,7 @@ sk_imagefilter_t* sk_runtimeeffect_make_image_filter(sk_runtimeeffect_t* effect, } std::string_view name = childShaderName ? std::string_view(childShaderName) : std::string_view(); - return ToImageFilter(SkImageFilters::RuntimeShader(builder, name, sk_ref_sp(AsImageFilter(input))).release()); + return ToImageFilter(SkImageFilters::RuntimeShader(builder, maxSampleRadius, name, sk_ref_sp(AsImageFilter(input))).release()); } sk_imagefilter_t* sk_runtimeeffect_make_image_filter_with_children(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount, float maxSampleRadius, const char** childShaderNames, const sk_imagefilter_t** inputs, int inputCount) {