xref: /aosp_15_r20/frameworks/base/media/mca/filterfw/jni/jni_gl_frame.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "android/bitmap.h"
18 
19 #include "jni/jni_gl_frame.h"
20 #include "jni/jni_util.h"
21 
22 #include "native/core/gl_env.h"
23 #include "native/core/gl_frame.h"
24 #include "native/core/native_frame.h"
25 
26 using android::filterfw::GLEnv;
27 using android::filterfw::GLFrame;
28 using android::filterfw::NativeFrame;
29 
30 // Helper functions ////////////////////////////////////////////////////////////////////////////////
ConvertFloatsToRGBA(const float * floats,int length,uint8_t * result)31 void ConvertFloatsToRGBA(const float* floats, int length, uint8_t* result) {
32   for (int i = 0; i < length; ++i) {
33     result[i] = static_cast<uint8_t>(floats[i] * 255.0);
34   }
35 }
36 
ConvertRGBAToFloats(const uint8_t * rgba,int length,float * result)37 void ConvertRGBAToFloats(const uint8_t* rgba, int length, float* result) {
38   for (int i = 0; i < length; ++i) {
39     result[i] = rgba[i] / 255.0;
40   }
41 }
42 
43 // GLFrame JNI implementation //////////////////////////////////////////////////////////////////////
Java_android_filterfw_core_GLFrame_nativeAllocate(JNIEnv * env,jobject thiz,jobject gl_env,jint width,jint height)44 jboolean Java_android_filterfw_core_GLFrame_nativeAllocate(JNIEnv* env,
45                                                            jobject thiz,
46                                                            jobject gl_env,
47                                                            jint width,
48                                                            jint height) {
49   GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
50   if (!gl_env_ptr) return JNI_FALSE;
51   std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
52   if (frame->Init(width, height)) {
53     return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
54   }
55   return JNI_FALSE;
56 }
57 
Java_android_filterfw_core_GLFrame_nativeAllocateWithTexture(JNIEnv * env,jobject thiz,jobject gl_env,jint tex_id,jint width,jint height)58 jboolean Java_android_filterfw_core_GLFrame_nativeAllocateWithTexture(JNIEnv* env,
59                                                                       jobject thiz,
60                                                                       jobject gl_env,
61                                                                       jint tex_id,
62                                                                       jint width,
63                                                                       jint height) {
64   GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
65   if (!gl_env_ptr) return JNI_FALSE;
66   std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
67   if (frame->InitWithTexture(tex_id, width, height)) {
68     return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
69   }
70   return JNI_FALSE;
71 }
72 
Java_android_filterfw_core_GLFrame_nativeAllocateWithFbo(JNIEnv * env,jobject thiz,jobject gl_env,jint fbo_id,jint width,jint height)73 jboolean Java_android_filterfw_core_GLFrame_nativeAllocateWithFbo(JNIEnv* env,
74                                                                   jobject thiz,
75                                                                   jobject gl_env,
76                                                                   jint fbo_id,
77                                                                   jint width,
78                                                                   jint height) {
79   GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
80   if (!gl_env_ptr) return JNI_FALSE;
81   std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
82   if (frame->InitWithFbo(fbo_id, width, height)) {
83     return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
84   }
85   return JNI_FALSE;
86 }
87 
Java_android_filterfw_core_GLFrame_nativeAllocateExternal(JNIEnv * env,jobject thiz,jobject gl_env)88 jboolean Java_android_filterfw_core_GLFrame_nativeAllocateExternal(JNIEnv* env,
89                                                                    jobject thiz,
90                                                                    jobject gl_env) {
91   GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
92   if (!gl_env_ptr) return JNI_FALSE;
93   std::unique_ptr<GLFrame> frame(new GLFrame(gl_env_ptr));
94   if (frame->InitWithExternalTexture()) {
95     return ToJBool(WrapOwnedObjectInJava(std::move(frame), env, thiz, true));
96   }
97   return JNI_FALSE;
98 }
99 
Java_android_filterfw_core_GLFrame_nativeDeallocate(JNIEnv * env,jobject thiz)100 jboolean Java_android_filterfw_core_GLFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
101   return ToJBool(DeleteNativeObject<GLFrame>(env, thiz));
102 }
103 
Java_android_filterfw_core_GLFrame_setNativeData(JNIEnv * env,jobject thiz,jbyteArray data,jint offset,jint length)104 jboolean Java_android_filterfw_core_GLFrame_setNativeData(JNIEnv* env,
105                                                           jobject thiz,
106                                                           jbyteArray data,
107                                                           jint offset,
108                                                           jint length) {
109   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
110   if (frame && data) {
111     jbyte* bytes = env->GetByteArrayElements(data, NULL);
112     if (bytes) {
113       const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(bytes + offset), length);
114       env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
115       return ToJBool(success);
116     }
117   }
118   return JNI_FALSE;
119 }
120 
Java_android_filterfw_core_GLFrame_getNativeData(JNIEnv * env,jobject thiz)121 jbyteArray Java_android_filterfw_core_GLFrame_getNativeData(JNIEnv* env, jobject thiz) {
122   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
123   if (frame && frame->Size() > 0) {
124     jbyteArray result = env->NewByteArray(frame->Size());
125     jbyte* data = env->GetByteArrayElements(result, NULL);
126     frame->CopyDataTo(reinterpret_cast<uint8_t*>(data), frame->Size());
127     env->ReleaseByteArrayElements(result, data, 0);
128     return result;
129   }
130   return NULL;
131 }
132 
Java_android_filterfw_core_GLFrame_setNativeInts(JNIEnv * env,jobject thiz,jintArray ints)133 jboolean Java_android_filterfw_core_GLFrame_setNativeInts(JNIEnv* env,
134                                                           jobject thiz,
135                                                           jintArray ints) {
136   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
137   if (frame && ints) {
138     jint* int_ptr = env->GetIntArrayElements(ints, NULL);
139     const int length = env->GetArrayLength(ints);
140     if (int_ptr) {
141       const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(int_ptr),
142                                             length * sizeof(jint));
143       env->ReleaseIntArrayElements(ints, int_ptr, JNI_ABORT);
144       return ToJBool(success);
145     }
146   }
147   return JNI_FALSE;
148 }
149 
Java_android_filterfw_core_GLFrame_getNativeInts(JNIEnv * env,jobject thiz)150 jintArray Java_android_filterfw_core_GLFrame_getNativeInts(JNIEnv* env, jobject thiz) {
151   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
152   if (frame && frame->Size() > 0 && (frame->Size() % sizeof(jint) == 0)) {
153     jintArray result = env->NewIntArray(frame->Size() / sizeof(jint));
154     jint* data = env->GetIntArrayElements(result, NULL);
155     frame->CopyDataTo(reinterpret_cast<uint8_t*>(data), frame->Size());
156     env->ReleaseIntArrayElements(result, data, 0);
157     return result;
158    }
159    return NULL;
160 }
161 
Java_android_filterfw_core_GLFrame_setNativeFloats(JNIEnv * env,jobject thiz,jfloatArray floats)162 jboolean Java_android_filterfw_core_GLFrame_setNativeFloats(JNIEnv* env,
163                                                             jobject thiz,
164                                                             jfloatArray floats) {
165   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
166   if (frame && floats) {
167     jfloat* float_ptr = env->GetFloatArrayElements(floats, NULL);
168     const int length = env->GetArrayLength(floats);
169     if (float_ptr) {
170       // Convert floats to RGBA buffer
171       uint8_t* rgba_buffer = new uint8_t[length];
172       ConvertFloatsToRGBA(float_ptr, length, rgba_buffer);
173       env->ReleaseFloatArrayElements(floats, float_ptr, JNI_ABORT);
174 
175       // Write RGBA buffer to frame
176       const bool success = frame->WriteData(rgba_buffer, length);
177 
178       // Clean-up
179       delete[] rgba_buffer;
180       return ToJBool(success);
181     }
182   }
183   return JNI_FALSE;
184 }
185 
Java_android_filterfw_core_GLFrame_getNativeFloats(JNIEnv * env,jobject thiz)186 jfloatArray Java_android_filterfw_core_GLFrame_getNativeFloats(JNIEnv* env, jobject thiz) {
187   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
188   if (frame && frame->Size() > 0) {
189     // Create the result array
190     jfloatArray result = env->NewFloatArray(frame->Size());
191     jfloat* float_array = env->GetFloatArrayElements(result, NULL);
192 
193     // Read the frame pixels
194     uint8_t* pixels = new uint8_t[frame->Size()];
195     frame->CopyDataTo(pixels, frame->Size());
196 
197     // Convert them to floats
198     ConvertRGBAToFloats(pixels, frame->Size(), float_array);
199 
200     // Clean-up
201     delete[] pixels;
202     env->ReleaseFloatArrayElements(result, float_array, 0);
203     return result;
204   }
205   return NULL;
206 }
207 
Java_android_filterfw_core_GLFrame_setNativeBitmap(JNIEnv * env,jobject thiz,jobject bitmap,jint size)208 jboolean Java_android_filterfw_core_GLFrame_setNativeBitmap(JNIEnv* env,
209                                                             jobject thiz,
210                                                             jobject bitmap,
211                                                             jint size) {
212   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
213   if (frame && bitmap) {
214     uint8_t* pixels;
215     const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&pixels));
216     if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
217       const bool success = frame->WriteData(pixels, size);
218       return ToJBool(success &&
219                      AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
220     }
221   }
222   return JNI_FALSE;
223 }
224 
Java_android_filterfw_core_GLFrame_getNativeBitmap(JNIEnv * env,jobject thiz,jobject bitmap)225 jboolean Java_android_filterfw_core_GLFrame_getNativeBitmap(JNIEnv* env,
226                                                             jobject thiz,
227                                                             jobject bitmap) {
228   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
229   if (frame && bitmap) {
230     uint8_t* pixels;
231     const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&pixels));
232     if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
233       frame->CopyDataTo(pixels, frame->Size());
234       return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
235     }
236   }
237   return JNI_FALSE;
238 }
239 
Java_android_filterfw_core_GLFrame_setNativeViewport(JNIEnv * env,jobject thiz,jint x,jint y,jint width,jint height)240 jboolean Java_android_filterfw_core_GLFrame_setNativeViewport(JNIEnv* env,
241                                                               jobject thiz,
242                                                               jint x,
243                                                               jint y,
244                                                               jint width,
245                                                               jint height) {
246   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
247   return frame ? ToJBool(frame->SetViewport(x, y, width, height)) : JNI_FALSE;
248 }
249 
Java_android_filterfw_core_GLFrame_getNativeTextureId(JNIEnv * env,jobject thiz)250 jint Java_android_filterfw_core_GLFrame_getNativeTextureId(JNIEnv* env, jobject thiz) {
251   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
252   return frame ? frame->GetTextureId() : -1;
253 }
254 
Java_android_filterfw_core_GLFrame_getNativeFboId(JNIEnv * env,jobject thiz)255 jint Java_android_filterfw_core_GLFrame_getNativeFboId(JNIEnv* env, jobject thiz) {
256   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
257   return frame ? frame->GetFboId() : -1;
258 }
259 
Java_android_filterfw_core_GLFrame_generateNativeMipMap(JNIEnv * env,jobject thiz)260 jboolean Java_android_filterfw_core_GLFrame_generateNativeMipMap(JNIEnv* env, jobject thiz) {
261   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
262   return frame ? ToJBool(frame->GenerateMipMap()) : JNI_FALSE;
263 }
264 
Java_android_filterfw_core_GLFrame_setNativeTextureParam(JNIEnv * env,jobject thiz,jint param,jint value)265 jboolean Java_android_filterfw_core_GLFrame_setNativeTextureParam(JNIEnv* env,
266                                                                   jobject thiz,
267                                                                   jint param,
268                                                                   jint value) {
269   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
270   return frame ? ToJBool(frame->SetTextureParameter(param, value)) : JNI_FALSE;
271 }
272 
Java_android_filterfw_core_GLFrame_nativeResetParams(JNIEnv * env,jobject thiz)273 jboolean Java_android_filterfw_core_GLFrame_nativeResetParams(JNIEnv* env, jobject thiz) {
274   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
275   return frame ? ToJBool(frame->ResetTexParameters()) : JNI_FALSE;
276 }
277 
Java_android_filterfw_core_GLFrame_nativeCopyFromNative(JNIEnv * env,jobject thiz,jobject frame)278 jboolean Java_android_filterfw_core_GLFrame_nativeCopyFromNative(JNIEnv* env,
279                                                                  jobject thiz,
280                                                                  jobject frame) {
281   GLFrame* this_frame = ConvertFromJava<GLFrame>(env, thiz);
282   NativeFrame* other_frame = ConvertFromJava<NativeFrame>(env, frame);
283   if (this_frame && other_frame) {
284     return ToJBool(this_frame->WriteData(other_frame->Data(), other_frame->Size()));
285   }
286   return JNI_FALSE;
287 }
288 
Java_android_filterfw_core_GLFrame_nativeCopyFromGL(JNIEnv * env,jobject thiz,jobject frame)289 jboolean Java_android_filterfw_core_GLFrame_nativeCopyFromGL(JNIEnv* env,
290                                                              jobject thiz,
291                                                              jobject frame) {
292   GLFrame* this_frame = ConvertFromJava<GLFrame>(env, thiz);
293   GLFrame* other_frame = ConvertFromJava<GLFrame>(env, frame);
294   if (this_frame && other_frame) {
295     return ToJBool(this_frame->CopyPixelsFrom(other_frame));
296   }
297   return JNI_FALSE;
298 }
299 
Java_android_filterfw_core_GLFrame_nativeFocus(JNIEnv * env,jobject thiz)300 jboolean Java_android_filterfw_core_GLFrame_nativeFocus(JNIEnv* env, jobject thiz) {
301   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
302   return ToJBool(frame && frame->FocusFrameBuffer());
303 }
304 
Java_android_filterfw_core_GLFrame_nativeReattachTexToFbo(JNIEnv * env,jobject thiz)305 jboolean Java_android_filterfw_core_GLFrame_nativeReattachTexToFbo(JNIEnv* env, jobject thiz) {
306   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
307   return ToJBool(frame && frame->ReattachTextureToFbo());
308 }
309 
Java_android_filterfw_core_GLFrame_nativeDetachTexFromFbo(JNIEnv * env,jobject thiz)310 jboolean Java_android_filterfw_core_GLFrame_nativeDetachTexFromFbo(JNIEnv* env, jobject thiz) {
311   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
312   return ToJBool(frame && frame->DetachTextureFromFbo());
313 }
314 
315