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