xref: /aosp_15_r20/frameworks/base/libs/hwui/jni/ColorFilter.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /* libs/android_runtime/android/graphics/ColorFilter.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "ColorFilter.h"
19 
20 #include "GraphicsJNI.h"
21 #include "RuntimeEffectUtils.h"
22 #include "SkBlendMode.h"
23 #include "include/effects/SkRuntimeEffect.h"
24 
25 namespace android {
26 
27 using namespace uirenderer;
28 
29 class ColorFilterGlue {
30 public:
SafeUnref(ColorFilter * filter)31     static void SafeUnref(ColorFilter* filter) {
32         if (filter) {
33             filter->decStrong(nullptr);
34         }
35     }
36 
GetNativeFinalizer(JNIEnv *,jobject)37     static jlong GetNativeFinalizer(JNIEnv*, jobject) {
38         return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SafeUnref));
39     }
40 
CreateBlendModeFilter(JNIEnv * env,jobject,jint srcColor,jint modeHandle)41     static jlong CreateBlendModeFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) {
42         auto mode = static_cast<SkBlendMode>(modeHandle);
43         auto* blendModeFilter = new BlendModeColorFilter(srcColor, mode);
44         blendModeFilter->incStrong(nullptr);
45         return static_cast<jlong>(reinterpret_cast<uintptr_t>(blendModeFilter));
46     }
47 
CreateLightingFilter(JNIEnv * env,jobject,jint mul,jint add)48     static jlong CreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) {
49         auto* lightingFilter = new LightingFilter(mul, add);
50         lightingFilter->incStrong(nullptr);
51         return static_cast<jlong>(reinterpret_cast<uintptr_t>(lightingFilter));
52     }
53 
SetLightingFilterMul(JNIEnv * env,jobject,jlong lightingFilterPtr,jint mul)54     static void SetLightingFilterMul(JNIEnv* env, jobject, jlong lightingFilterPtr, jint mul) {
55         auto* filter = reinterpret_cast<LightingFilter*>(lightingFilterPtr);
56         if (filter) {
57             filter->setMul(mul);
58         }
59     }
60 
SetLightingFilterAdd(JNIEnv * env,jobject,jlong lightingFilterPtr,jint add)61     static void SetLightingFilterAdd(JNIEnv* env, jobject, jlong lightingFilterPtr, jint add) {
62         auto* filter = reinterpret_cast<LightingFilter*>(lightingFilterPtr);
63         if (filter) {
64             filter->setAdd(add);
65         }
66     }
67 
getMatrixFromJFloatArray(JNIEnv * env,jfloatArray jarray)68     static std::vector<float> getMatrixFromJFloatArray(JNIEnv* env, jfloatArray jarray) {
69         std::vector<float> matrix(20);
70         // float matrix[20];
71         env->GetFloatArrayRegion(jarray, 0, 20, matrix.data());
72         // java biases the translates by 255, so undo that before calling skia
73         matrix[ 4] *= (1.0f/255);
74         matrix[ 9] *= (1.0f/255);
75         matrix[14] *= (1.0f/255);
76         matrix[19] *= (1.0f/255);
77         return matrix;
78     }
79 
CreateColorMatrixFilter(JNIEnv * env,jobject,jfloatArray jarray)80     static jlong CreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) {
81         std::vector<float> matrix = getMatrixFromJFloatArray(env, jarray);
82         auto* colorMatrixColorFilter = new ColorMatrixColorFilter(std::move(matrix));
83         colorMatrixColorFilter->incStrong(nullptr);
84         return static_cast<jlong>(reinterpret_cast<uintptr_t>(colorMatrixColorFilter));
85     }
86 
SetColorMatrix(JNIEnv * env,jobject,jlong colorMatrixColorFilterPtr,jfloatArray jarray)87     static void SetColorMatrix(JNIEnv* env, jobject, jlong colorMatrixColorFilterPtr,
88                                jfloatArray jarray) {
89         auto* filter = reinterpret_cast<ColorMatrixColorFilter*>(colorMatrixColorFilterPtr);
90         if (filter) {
91             filter->setMatrix(getMatrixFromJFloatArray(env, jarray));
92         }
93     }
94 
RuntimeColorFilter_createColorFilter(JNIEnv * env,jobject,jstring agsl)95     static jlong RuntimeColorFilter_createColorFilter(JNIEnv* env, jobject, jstring agsl) {
96         ScopedUtfChars strSksl(env, agsl);
97         auto result = SkRuntimeEffect::MakeForColorFilter(SkString(strSksl.c_str()),
98                                                           SkRuntimeEffect::Options{});
99         if (result.effect.get() == nullptr) {
100             doThrowIAE(env, result.errorText.c_str());
101             return 0;
102         }
103         auto builder = new SkRuntimeEffectBuilder(std::move(result.effect));
104         auto* runtimeColorFilter = new RuntimeColorFilter(builder);
105         runtimeColorFilter->incStrong(nullptr);
106         return static_cast<jlong>(reinterpret_cast<uintptr_t>(runtimeColorFilter));
107     }
108 
RuntimeColorFilter_updateUniformsFloatArray(JNIEnv * env,jobject,jlong colorFilterPtr,jstring uniformName,jfloatArray uniforms,jboolean isColor)109     static void RuntimeColorFilter_updateUniformsFloatArray(JNIEnv* env, jobject,
110                                                             jlong colorFilterPtr,
111                                                             jstring uniformName,
112                                                             jfloatArray uniforms,
113                                                             jboolean isColor) {
114         auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr);
115         ScopedUtfChars name(env, uniformName);
116         AutoJavaFloatArray autoValues(env, uniforms, 0, kRO_JNIAccess);
117         if (filter) {
118             filter->updateUniforms(env, name.c_str(), autoValues.ptr(), autoValues.length(),
119                                    isColor);
120         }
121     }
122 
RuntimeColorFilter_updateUniformsFloats(JNIEnv * env,jobject,jlong colorFilterPtr,jstring uniformName,jfloat value1,jfloat value2,jfloat value3,jfloat value4,jint count)123     static void RuntimeColorFilter_updateUniformsFloats(JNIEnv* env, jobject, jlong colorFilterPtr,
124                                                         jstring uniformName, jfloat value1,
125                                                         jfloat value2, jfloat value3, jfloat value4,
126                                                         jint count) {
127         auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr);
128         ScopedUtfChars name(env, uniformName);
129         const float values[4] = {value1, value2, value3, value4};
130         if (filter) {
131             filter->updateUniforms(env, name.c_str(), values, count, false);
132         }
133     }
134 
RuntimeColorFilter_updateUniformsIntArray(JNIEnv * env,jobject,jlong colorFilterPtr,jstring uniformName,jintArray uniforms)135     static void RuntimeColorFilter_updateUniformsIntArray(JNIEnv* env, jobject,
136                                                           jlong colorFilterPtr, jstring uniformName,
137                                                           jintArray uniforms) {
138         auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr);
139         ScopedUtfChars name(env, uniformName);
140         AutoJavaIntArray autoValues(env, uniforms, 0);
141         if (filter) {
142             filter->updateUniforms(env, name.c_str(), autoValues.ptr(), autoValues.length());
143         }
144     }
145 
RuntimeColorFilter_updateUniformsInts(JNIEnv * env,jobject,jlong colorFilterPtr,jstring uniformName,jint value1,jint value2,jint value3,jint value4,jint count)146     static void RuntimeColorFilter_updateUniformsInts(JNIEnv* env, jobject, jlong colorFilterPtr,
147                                                       jstring uniformName, jint value1, jint value2,
148                                                       jint value3, jint value4, jint count) {
149         auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr);
150         ScopedUtfChars name(env, uniformName);
151         const int values[4] = {value1, value2, value3, value4};
152         if (filter) {
153             filter->updateUniforms(env, name.c_str(), values, count);
154         }
155     }
156 
RuntimeColorFilter_updateChild(JNIEnv * env,jobject,jlong colorFilterPtr,jstring childName,jlong childPtr)157     static void RuntimeColorFilter_updateChild(JNIEnv* env, jobject, jlong colorFilterPtr,
158                                                jstring childName, jlong childPtr) {
159         auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr);
160         ScopedUtfChars name(env, childName);
161         auto* child = reinterpret_cast<SkFlattenable*>(childPtr);
162         if (filter && child) {
163             filter->updateChild(env, name.c_str(), child);
164         }
165     }
166 
RuntimeColorFilter_updateInputColorFilter(JNIEnv * env,jobject,jlong colorFilterPtr,jstring childName,jlong childFilterPtr)167     static void RuntimeColorFilter_updateInputColorFilter(JNIEnv* env, jobject,
168                                                           jlong colorFilterPtr, jstring childName,
169                                                           jlong childFilterPtr) {
170         auto* filter = reinterpret_cast<RuntimeColorFilter*>(colorFilterPtr);
171         ScopedUtfChars name(env, childName);
172         auto* child = reinterpret_cast<ColorFilter*>(childFilterPtr);
173         if (filter && child) {
174             auto childInput = child->getInstance();
175             if (childInput) {
176                 filter->updateChild(env, name.c_str(), childInput.release());
177             }
178         }
179     }
180 };
181 
182 static const JNINativeMethod colorfilter_methods[] = {
183         {"nativeGetFinalizer", "()J", (void*)ColorFilterGlue::GetNativeFinalizer}};
184 
185 static const JNINativeMethod blendmode_methods[] = {
186         {"native_CreateBlendModeFilter", "(II)J", (void*)ColorFilterGlue::CreateBlendModeFilter},
187 };
188 
189 static const JNINativeMethod lighting_methods[] = {
190         {"native_CreateLightingFilter", "(II)J", (void*)ColorFilterGlue::CreateLightingFilter},
191         {"native_SetLightingFilterAdd", "(JI)V", (void*)ColorFilterGlue::SetLightingFilterAdd},
192         {"native_SetLightingFilterMul", "(JI)V", (void*)ColorFilterGlue::SetLightingFilterMul}};
193 
194 static const JNINativeMethod colormatrix_methods[] = {
195         {"nativeColorMatrixFilter", "([F)J", (void*)ColorFilterGlue::CreateColorMatrixFilter},
196         {"nativeSetColorMatrix", "(J[F)V", (void*)ColorFilterGlue::SetColorMatrix}};
197 
198 static const JNINativeMethod runtime_color_filter_methods[] = {
199         {"nativeCreateRuntimeColorFilter", "(Ljava/lang/String;)J",
200          (void*)ColorFilterGlue::RuntimeColorFilter_createColorFilter},
201         {"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V",
202          (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsFloatArray},
203         {"nativeUpdateUniforms", "(JLjava/lang/String;FFFFI)V",
204          (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsFloats},
205         {"nativeUpdateUniforms", "(JLjava/lang/String;[I)V",
206          (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsIntArray},
207         {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V",
208          (void*)ColorFilterGlue::RuntimeColorFilter_updateUniformsInts},
209         {"nativeUpdateChild", "(JLjava/lang/String;J)V",
210          (void*)ColorFilterGlue::RuntimeColorFilter_updateChild},
211         {"nativeUpdateInputColorFilter", "(JLjava/lang/String;J)V",
212          (void*)ColorFilterGlue::RuntimeColorFilter_updateInputColorFilter}};
213 
register_android_graphics_ColorFilter(JNIEnv * env)214 int register_android_graphics_ColorFilter(JNIEnv* env) {
215     android::RegisterMethodsOrDie(env, "android/graphics/ColorFilter", colorfilter_methods,
216                                   NELEM(colorfilter_methods));
217     android::RegisterMethodsOrDie(env, "android/graphics/PorterDuffColorFilter", blendmode_methods,
218                                   NELEM(blendmode_methods));
219     android::RegisterMethodsOrDie(env, "android/graphics/BlendModeColorFilter", blendmode_methods,
220                                   NELEM(blendmode_methods));
221     android::RegisterMethodsOrDie(env, "android/graphics/LightingColorFilter", lighting_methods,
222                                   NELEM(lighting_methods));
223     android::RegisterMethodsOrDie(env, "android/graphics/ColorMatrixColorFilter",
224                                   colormatrix_methods, NELEM(colormatrix_methods));
225     android::RegisterMethodsOrDie(env, "android/graphics/RuntimeColorFilter",
226                                   runtime_color_filter_methods,
227                                   NELEM(runtime_color_filter_methods));
228 
229     return 0;
230 }
231 
232 }
233