diff options
| author | 2024-10-31 15:00:52 +0000 | |
|---|---|---|
| committer | 2024-10-31 15:00:52 +0000 | |
| commit | 25e8d87e241516bea579a2c30f1de967012deeb4 (patch) | |
| tree | 2f7ae82e12f6ae3827c661cba544ed7175e00fdd | |
| parent | 70d69921ae62603eca7586ae09d49b9cc53b9401 (diff) | |
| parent | 2c9a6886e0c7321b7f27cf068058073ff1950028 (diff) | |
Merge "add runtime color filter support to platform" into main
| -rw-r--r-- | core/api/current.txt | 19 | ||||
| -rw-r--r-- | graphics/java/android/graphics/RuntimeColorFilter.java | 305 | ||||
| -rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
| -rw-r--r-- | libs/hwui/ColorFilter.h | 31 | ||||
| -rw-r--r-- | libs/hwui/jni/ColorFilter.cpp | 93 | ||||
| -rw-r--r-- | libs/hwui/jni/RuntimeEffectUtils.cpp | 101 | ||||
| -rw-r--r-- | libs/hwui/jni/RuntimeEffectUtils.h | 37 |
7 files changed, 586 insertions, 1 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 47ec2f91c385..0212fe3a58b3 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17361,6 +17361,25 @@ package android.graphics { method public boolean setUseCompositingLayer(boolean, @Nullable android.graphics.Paint); } + @FlaggedApi("com.android.graphics.hwui.flags.runtime_color_filters_blenders") public class RuntimeColorFilter extends android.graphics.ColorFilter { + ctor public RuntimeColorFilter(@NonNull String); + method public void setColorUniform(@NonNull String, @ColorInt int); + method public void setColorUniform(@NonNull String, @ColorLong long); + method public void setColorUniform(@NonNull String, @NonNull android.graphics.Color); + method public void setFloatUniform(@NonNull String, float); + method public void setFloatUniform(@NonNull String, float, float); + method public void setFloatUniform(@NonNull String, float, float, float); + method public void setFloatUniform(@NonNull String, float, float, float, float); + method public void setFloatUniform(@NonNull String, @NonNull float[]); + method public void setInputColorFilter(@NonNull String, @NonNull android.graphics.ColorFilter); + method public void setInputShader(@NonNull String, @NonNull android.graphics.Shader); + method public void setIntUniform(@NonNull String, int); + method public void setIntUniform(@NonNull String, int, int); + method public void setIntUniform(@NonNull String, int, int, int); + method public void setIntUniform(@NonNull String, int, int, int, int); + method public void setIntUniform(@NonNull String, @NonNull int[]); + } + public class RuntimeShader extends android.graphics.Shader { ctor public RuntimeShader(@NonNull String); method public void setColorUniform(@NonNull String, @ColorInt int); diff --git a/graphics/java/android/graphics/RuntimeColorFilter.java b/graphics/java/android/graphics/RuntimeColorFilter.java new file mode 100644 index 000000000000..52724ceaf301 --- /dev/null +++ b/graphics/java/android/graphics/RuntimeColorFilter.java @@ -0,0 +1,305 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.annotation.ColorInt; +import android.annotation.ColorLong; +import android.annotation.FlaggedApi; +import android.annotation.NonNull; + +import com.android.graphics.hwui.flags.Flags; + + +/** + * <p>A {@link RuntimeColorFilter} calculates a per-pixel color based on the output of a user + * * defined Android Graphics Shading Language (AGSL) function.</p> + * + * <p>This AGSL function takes in an input color to be operated on. This color is in sRGB and the + * * output is also interpreted as sRGB. The AGSL function signature expects a single input + * * of color (packed as a half4 or float4 or vec4).</p> + * + * <pre class="prettyprint"> + * vec4 main(half4 in_color); + * </pre> + */ +@FlaggedApi(Flags.FLAG_RUNTIME_COLOR_FILTERS_BLENDERS) +public class RuntimeColorFilter extends ColorFilter { + + private String mAgsl; + + /** + * Creates a new RuntimeColorFilter. + * + * @param agsl The text of AGSL color filter program to run. + */ + public RuntimeColorFilter(@NonNull String agsl) { + if (agsl == null) { + throw new NullPointerException("RuntimeColorFilter requires a non-null AGSL string"); + } + mAgsl = agsl; + // call to parent class to register native RuntimeColorFilter + // TODO: find way to get super class to create native instance without requiring the storage + // of agsl string + getNativeInstance(); + + } + /** + * Sets the uniform color value corresponding to this color filter. If the effect does not have + * a uniform with that name or if the uniform is declared with a type other than vec3 or vec4 + * and corresponding layout(color) annotation then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the color uniform declared in the AGSL program + * @param color the provided sRGB color + */ + public void setColorUniform(@NonNull String uniformName, @ColorInt int color) { + setUniform(uniformName, Color.valueOf(color).getComponents(), true); + } + + /** + * Sets the uniform color value corresponding to this color filter. If the effect does not have + * a uniform with that name or if the uniform is declared with a type other than vec3 or vec4 + * and corresponding layout(color) annotation then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the color uniform declared in the AGSL program + * @param color the provided sRGB color + */ + public void setColorUniform(@NonNull String uniformName, @ColorLong long color) { + Color exSRGB = Color.valueOf(color).convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)); + setUniform(uniformName, exSRGB.getComponents(), true); + } + + /** + * Sets the uniform color value corresponding to this color filter. If the effect does not have + * a uniform with that name or if the uniform is declared with a type other than vec3 or vec4 + * and corresponding layout(color) annotation then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the color uniform declared in the AGSL program + * @param color the provided sRGB color + */ + public void setColorUniform(@NonNull String uniformName, @NonNull Color color) { + if (color == null) { + throw new NullPointerException("The color parameter must not be null"); + } + Color exSRGB = color.convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)); + setUniform(uniformName, exSRGB.getComponents(), true); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than a float or + * float[1] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setFloatUniform(@NonNull String uniformName, float value) { + setFloatUniform(uniformName, value, 0.0f, 0.0f, 0.0f, 1); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than a vec2 or + * float[2] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setFloatUniform(@NonNull String uniformName, float value1, float value2) { + setFloatUniform(uniformName, value1, value2, 0.0f, 0.0f, 2); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than a vec3 or + * float[3] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setFloatUniform(@NonNull String uniformName, float value1, float value2, + float value3) { + setFloatUniform(uniformName, value1, value2, value3, 0.0f, 3); + + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than a vec4 or + * float[4] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setFloatUniform(@NonNull String uniformName, float value1, float value2, + float value3, float value4) { + setFloatUniform(uniformName, value1, value2, value3, value4, 4); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than a float + * (for N=1), vecN, or float[N] where N is the length of the values param then an + * IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setFloatUniform(@NonNull String uniformName, @NonNull float[] values) { + setUniform(uniformName, values, false); + } + + private void setFloatUniform(@NonNull String uniformName, float value1, float value2, + float value3, float value4, int count) { + if (uniformName == null) { + throw new NullPointerException("The uniformName parameter must not be null"); + } + nativeUpdateUniforms(getNativeInstance(), uniformName, value1, value2, value3, value4, + count); + } + + private void setUniform(@NonNull String uniformName, @NonNull float[] values, boolean isColor) { + if (uniformName == null) { + throw new NullPointerException("The uniformName parameter must not be null"); + } + if (values == null) { + throw new NullPointerException("The uniform values parameter must not be null"); + } + nativeUpdateUniforms(getNativeInstance(), uniformName, values, isColor); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than an int or int[1] + * then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setIntUniform(@NonNull String uniformName, int value) { + setIntUniform(uniformName, value, 0, 0, 0, 1); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than an ivec2 or + * int[2] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setIntUniform(@NonNull String uniformName, int value1, int value2) { + setIntUniform(uniformName, value1, value2, 0, 0, 2); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than an ivec3 or + * int[3] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setIntUniform(@NonNull String uniformName, int value1, int value2, int value3) { + setIntUniform(uniformName, value1, value2, value3, 0, 3); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than an ivec4 or + * int[4] then an IllegalArgumentException is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setIntUniform(@NonNull String uniformName, int value1, int value2, + int value3, int value4) { + setIntUniform(uniformName, value1, value2, value3, value4, 4); + } + + /** + * Sets the uniform value corresponding to this color filter. If the effect does not have a + * uniform with that name or if the uniform is declared with a type other than an int (for N=1), + * ivecN, or int[N] where N is the length of the values param then an IllegalArgumentException + * is thrown. + * + * @param uniformName name matching the uniform declared in the AGSL program + */ + public void setIntUniform(@NonNull String uniformName, @NonNull int[] values) { + if (uniformName == null) { + throw new NullPointerException("The uniformName parameter must not be null"); + } + if (values == null) { + throw new NullPointerException("The uniform values parameter must not be null"); + } + nativeUpdateUniforms(getNativeInstance(), uniformName, values); + } + + private void setIntUniform(@NonNull String uniformName, int value1, int value2, int value3, + int value4, int count) { + if (uniformName == null) { + throw new NullPointerException("The uniformName parameter must not be null"); + } + nativeUpdateUniforms(getNativeInstance(), uniformName, value1, value2, value3, value4, + count); + } + + /** + * Assigns the uniform shader to the provided shader parameter. If the shader program does not + * have a uniform shader with that name then an IllegalArgumentException is thrown. + * + * @param shaderName name matching the uniform declared in the AGSL program + * @param shader shader passed into the AGSL program for sampling + */ + public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) { + if (shaderName == null) { + throw new NullPointerException("The shaderName parameter must not be null"); + } + if (shader == null) { + throw new NullPointerException("The shader parameter must not be null"); + } + nativeUpdateChild(getNativeInstance(), shaderName, shader.getNativeInstance()); + } + + /** + * Assigns the uniform color filter to the provided color filter parameter. If the shader + * program does not have a uniform color filter with that name then an IllegalArgumentException + * is thrown. + * + * @param filterName name matching the uniform declared in the AGSL program + * @param colorFilter filter passed into the AGSL program for sampling + */ + public void setInputColorFilter(@NonNull String filterName, @NonNull ColorFilter colorFilter) { + if (filterName == null) { + throw new NullPointerException("The filterName parameter must not be null"); + } + if (colorFilter == null) { + throw new NullPointerException("The colorFilter parameter must not be null"); + } + nativeUpdateChild(getNativeInstance(), filterName, colorFilter.getNativeInstance()); + } + + /** @hide */ + @Override + protected long createNativeInstance() { + return nativeCreateRuntimeColorFilter(mAgsl); + } + + private static native long nativeCreateRuntimeColorFilter(String agsl); + private static native void nativeUpdateUniforms( + long colorFilter, String uniformName, float[] uniforms, boolean isColor); + private static native void nativeUpdateUniforms( + long colorFilter, String uniformName, float value1, float value2, float value3, + float value4, int count); + private static native void nativeUpdateUniforms( + long colorFilter, String uniformName, int[] uniforms); + private static native void nativeUpdateUniforms( + long colorFilter, String uniformName, int value1, int value2, int value3, + int value4, int count); + private static native void nativeUpdateChild(long colorFilter, String childName, long child); + +} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index d93ad4e3255b..fcb7efc35c94 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -384,6 +384,7 @@ cc_defaults { "jni/ScopedParcel.cpp", "jni/Shader.cpp", "jni/RenderEffect.cpp", + "jni/RuntimeEffectUtils.cpp", "jni/Typeface.cpp", "jni/Utils.cpp", "jni/YuvToJpegEncoder.cpp", diff --git a/libs/hwui/ColorFilter.h b/libs/hwui/ColorFilter.h index 3a3bfb47dfdd..f6b6be08997a 100644 --- a/libs/hwui/ColorFilter.h +++ b/libs/hwui/ColorFilter.h @@ -22,6 +22,7 @@ #include <memory> #include "GraphicsJNI.h" +#include "RuntimeEffectUtils.h" #include "SkColorFilter.h" namespace android { @@ -113,6 +114,36 @@ private: std::vector<float> mMatrix; }; +class RuntimeColorFilter : public ColorFilter { +public: + RuntimeColorFilter(SkRuntimeEffectBuilder* builder) : mBuilder(builder) {} + + void updateUniforms(JNIEnv* env, const char* name, const float vals[], int count, + bool isColor) { + UpdateFloatUniforms(env, mBuilder, name, vals, count, isColor); + discardInstance(); + } + + void updateUniforms(JNIEnv* env, const char* name, const int vals[], int count) { + UpdateIntUniforms(env, mBuilder, name, vals, count); + discardInstance(); + } + + void updateChild(JNIEnv* env, const char* name, SkFlattenable* childEffect) { + UpdateChild(env, mBuilder, name, childEffect); + discardInstance(); + } + +private: + sk_sp<SkColorFilter> createInstance() override { + // TODO: throw error if null + return mBuilder->makeColorFilter(); + } + +private: + SkRuntimeEffectBuilder* mBuilder; +}; + } // namespace uirenderer } // namespace android diff --git a/libs/hwui/jni/ColorFilter.cpp b/libs/hwui/jni/ColorFilter.cpp index 0b95148d3c82..20301d2c76ec 100644 --- a/libs/hwui/jni/ColorFilter.cpp +++ b/libs/hwui/jni/ColorFilter.cpp @@ -18,7 +18,9 @@ #include "ColorFilter.h" #include "GraphicsJNI.h" +#include "RuntimeEffectUtils.h" #include "SkBlendMode.h" +#include "include/effects/SkRuntimeEffect.h" namespace android { @@ -89,6 +91,78 @@ public: filter->setMatrix(getMatrixFromJFloatArray(env, jarray)); } } + + static jlong RuntimeColorFilter_createColorFilter(JNIEnv* env, jobject, jstring agsl) { + ScopedUtfChars strSksl(env, agsl); + auto result = SkRuntimeEffect::MakeForColorFilter(SkString(strSksl.c_str()), + SkRuntimeEffect::Options{}); + if (result.effect.get() == nullptr) { + doThrowIAE(env, result.errorText.c_str()); + return 0; + } + auto builder = new SkRuntimeEffectBuilder(std::move(result.effect)); + auto* runtimeColorFilter = new RuntimeColorFilter(builder); + runtimeColorFilter->incStrong(nullptr); + return static_cast<jlong>(reinterpret_cast<uintptr_t>(runtimeColorFilter)); + } + + static void RuntimeColorFilter_updateUniformsFloatArray(JNIEnv* env, jobject, + jlong colorFilterPtr, + jstring uniformName, + jfloatArray uniforms, + jboolean isColor) { + auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr); + ScopedUtfChars name(env, uniformName); + AutoJavaFloatArray autoValues(env, uniforms, 0, kRO_JNIAccess); + if (filter) { + filter->updateUniforms(env, name.c_str(), autoValues.ptr(), autoValues.length(), + isColor); + } + } + + static void RuntimeColorFilter_updateUniformsFloats(JNIEnv* env, jobject, jlong colorFilterPtr, + jstring uniformName, jfloat value1, + jfloat value2, jfloat value3, jfloat value4, + jint count) { + auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr); + ScopedUtfChars name(env, uniformName); + const float values[4] = {value1, value2, value3, value4}; + if (filter) { + filter->updateUniforms(env, name.c_str(), values, count, false); + } + } + + static void RuntimeColorFilter_updateUniformsIntArray(JNIEnv* env, jobject, + jlong colorFilterPtr, jstring uniformName, + jintArray uniforms) { + auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr); + ScopedUtfChars name(env, uniformName); + AutoJavaIntArray autoValues(env, uniforms, 0); + if (filter) { + filter->updateUniforms(env, name.c_str(), autoValues.ptr(), autoValues.length()); + } + } + + static void RuntimeColorFilter_updateUniformsInts(JNIEnv* env, jobject, jlong colorFilterPtr, + jstring uniformName, jint value1, jint value2, + jint value3, jint value4, jint count) { + auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr); + ScopedUtfChars name(env, uniformName); + const int values[4] = {value1, value2, value3, value4}; + if (filter) { + filter->updateUniforms(env, name.c_str(), values, count); + } + } + + static void RuntimeColorFilter_updateChild(JNIEnv* env, jobject, jlong colorFilterPtr, + jstring childName, jlong childPtr) { + auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr); + ScopedUtfChars name(env, childName); + auto* child = reinterpret_cast<SkFlattenable*>(childPtr); + if (filter && child) { + filter->updateChild(env, name.c_str(), child); + } + } }; static const JNINativeMethod colorfilter_methods[] = { @@ -107,6 +181,20 @@ static const JNINativeMethod colormatrix_methods[] = { {"nativeColorMatrixFilter", "([F)J", (void*)ColorFilterGlue::CreateColorMatrixFilter}, {"nativeSetColorMatrix", "(J[F)V", (void*)ColorFilterGlue::SetColorMatrix}}; +static const JNINativeMethod runtime_color_filter_methods[] = { + {"nativeCreateRuntimeColorFilter", "(Ljava/lang/String;)J", + (void*)ColorFilterGlue::RuntimeColorFilter_createColorFilter}, + {"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V", + (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsFloatArray}, + {"nativeUpdateUniforms", "(JLjava/lang/String;FFFFI)V", + (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsFloats}, + {"nativeUpdateUniforms", "(JLjava/lang/String;[I)V", + (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsIntArray}, + {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V", + (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsInts}, + {"nativeUpdateChild", "(JLjava/lang/String;J)V", + (void*)ColorFilterGlue::RuntimeColorFilter_updateChild}}; + int register_android_graphics_ColorFilter(JNIEnv* env) { android::RegisterMethodsOrDie(env, "android/graphics/ColorFilter", colorfilter_methods, NELEM(colorfilter_methods)); @@ -118,7 +206,10 @@ int register_android_graphics_ColorFilter(JNIEnv* env) { NELEM(lighting_methods)); android::RegisterMethodsOrDie(env, "android/graphics/ColorMatrixColorFilter", colormatrix_methods, NELEM(colormatrix_methods)); - + android::RegisterMethodsOrDie(env, "android/graphics/RuntimeColorFilter", + runtime_color_filter_methods, + NELEM(runtime_color_filter_methods)); + return 0; } diff --git a/libs/hwui/jni/RuntimeEffectUtils.cpp b/libs/hwui/jni/RuntimeEffectUtils.cpp new file mode 100644 index 000000000000..46db8633c66e --- /dev/null +++ b/libs/hwui/jni/RuntimeEffectUtils.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RuntimeEffectUtils.h" + +#include "include/effects/SkRuntimeEffect.h" + +namespace android { +namespace uirenderer { + +static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + int ret = jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args); + va_end(args); + return ret; +} + +bool isIntUniformType(const SkRuntimeEffect::Uniform::Type& type) { + switch (type) { + case SkRuntimeEffect::Uniform::Type::kFloat: + case SkRuntimeEffect::Uniform::Type::kFloat2: + case SkRuntimeEffect::Uniform::Type::kFloat3: + case SkRuntimeEffect::Uniform::Type::kFloat4: + case SkRuntimeEffect::Uniform::Type::kFloat2x2: + case SkRuntimeEffect::Uniform::Type::kFloat3x3: + case SkRuntimeEffect::Uniform::Type::kFloat4x4: + return false; + case SkRuntimeEffect::Uniform::Type::kInt: + case SkRuntimeEffect::Uniform::Type::kInt2: + case SkRuntimeEffect::Uniform::Type::kInt3: + case SkRuntimeEffect::Uniform::Type::kInt4: + return true; + } +} + +void UpdateFloatUniforms(JNIEnv* env, SkRuntimeEffectBuilder* builder, const char* uniformName, + const float values[], int count, bool isColor) { + SkRuntimeEffectBuilder::BuilderUniform uniform = builder->uniform(uniformName); + if (uniform.fVar == nullptr) { + ThrowIAEFmt(env, "unable to find uniform named %s", uniformName); + } else if (isColor != ((uniform.fVar->flags & SkRuntimeEffect::Uniform::kColor_Flag) != 0)) { + if (isColor) { + jniThrowExceptionFmt( + env, "java/lang/IllegalArgumentException", + "attempting to set a color uniform using the non-color specific APIs: %s %x", + uniformName, uniform.fVar->flags); + } else { + ThrowIAEFmt(env, + "attempting to set a non-color uniform using the setColorUniform APIs: %s", + uniformName); + } + } else if (isIntUniformType(uniform.fVar->type)) { + ThrowIAEFmt(env, "attempting to set a int uniform using the setUniform APIs: %s", + uniformName); + } else if (!uniform.set<float>(values, count)) { + ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]", + uniform.fVar->sizeInBytes(), sizeof(float) * count); + } +} + +void UpdateIntUniforms(JNIEnv* env, SkRuntimeEffectBuilder* builder, const char* uniformName, + const int values[], int count) { + SkRuntimeEffectBuilder::BuilderUniform uniform = builder->uniform(uniformName); + if (uniform.fVar == nullptr) { + ThrowIAEFmt(env, "unable to find uniform named %s", uniformName); + } else if (!isIntUniformType(uniform.fVar->type)) { + ThrowIAEFmt(env, "attempting to set a non-int uniform using the setIntUniform APIs: %s", + uniformName); + } else if (!uniform.set<int>(values, count)) { + ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]", + uniform.fVar->sizeInBytes(), sizeof(float) * count); + } +} + +void UpdateChild(JNIEnv* env, SkRuntimeEffectBuilder* builder, const char* childName, + SkFlattenable* childEffect) { + SkRuntimeShaderBuilder::BuilderChild builderChild = builder->child(childName); + if (builderChild.fChild == nullptr) { + ThrowIAEFmt(env, "unable to find shader named %s", childName); + return; + } + + builderChild = sk_ref_sp(childEffect); +} + +} // namespace uirenderer +} // namespace android
\ No newline at end of file diff --git a/libs/hwui/jni/RuntimeEffectUtils.h b/libs/hwui/jni/RuntimeEffectUtils.h new file mode 100644 index 000000000000..75623c0f7ac1 --- /dev/null +++ b/libs/hwui/jni/RuntimeEffectUtils.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RUNTIMEEFFECTUTILS_H +#define RUNTIMEEFFECTUTILS_H + +#include "GraphicsJNI.h" +#include "include/effects/SkRuntimeEffect.h" + +namespace android { +namespace uirenderer { + +void UpdateFloatUniforms(JNIEnv* env, SkRuntimeEffectBuilder* builder, const char* uniformName, + const float values[], int count, bool isColor); + +void UpdateIntUniforms(JNIEnv* env, SkRuntimeEffectBuilder* builder, const char* uniformName, + const int values[], int count); + +void UpdateChild(JNIEnv* env, SkRuntimeEffectBuilder* builder, const char* childName, + SkFlattenable* childEffect); +} // namespace uirenderer +} // namespace android + +#endif // MAIN_RUNTIMEEFFECTUTILS_H |