jni_gl_frame.cpp revision 511360e61650864ea22a171159efe073c80d0cdb
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
26using android::filterfw::GLEnv;
27using android::filterfw::GLFrame;
28using android::filterfw::NativeFrame;
29
30// Helper functions ////////////////////////////////////////////////////////////////////////////////
31void 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
37void 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 //////////////////////////////////////////////////////////////////////
44jboolean Java_android_filterfw_core_GLFrame_allocate(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  GLFrame* frame = new GLFrame(gl_env_ptr);
52  if (frame->Init(width, height)) {
53    return ToJBool(WrapObjectInJava(frame, env, thiz, true));
54  } else {
55    delete frame;
56    return JNI_FALSE;
57  }
58}
59
60jboolean Java_android_filterfw_core_GLFrame_allocateWithTexture(JNIEnv* env,
61                                                                jobject thiz,
62                                                                jobject gl_env,
63                                                                jint tex_id,
64                                                                jint width,
65                                                                jint height,
66                                                                jboolean owns,
67                                                                jboolean create) {
68  GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
69  if (!gl_env_ptr) return JNI_FALSE;
70  GLFrame* frame = new GLFrame(gl_env_ptr);
71  if (frame->InitWithTexture(tex_id, width, height, ToCppBool(owns), ToCppBool(create))) {
72    return ToJBool(WrapObjectInJava(frame, env, thiz, true));
73  } else {
74    delete frame;
75    return JNI_FALSE;
76  }
77}
78
79jboolean Java_android_filterfw_core_GLFrame_allocateWithFbo(JNIEnv* env,
80                                                            jobject thiz,
81                                                            jobject gl_env,
82                                                            jint fbo_id,
83                                                            jint width,
84                                                            jint height,
85                                                            jboolean owns,
86                                                            jboolean create) {
87  GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
88  if (!gl_env_ptr) return JNI_FALSE;
89  GLFrame* frame = new GLFrame(gl_env_ptr);
90  if (frame->InitWithFbo(fbo_id, width, height, ToCppBool(owns), ToCppBool(create))) {
91    return ToJBool(WrapObjectInJava(frame, env, thiz, true));
92  } else {
93    delete frame;
94    return JNI_FALSE;
95  }
96}
97
98jboolean Java_android_filterfw_core_GLFrame_allocateExternal(JNIEnv* env,
99                                                             jobject thiz,
100                                                             jobject gl_env) {
101  GLEnv* gl_env_ptr = ConvertFromJava<GLEnv>(env, gl_env);
102  if (!gl_env_ptr) return JNI_FALSE;
103  GLFrame* frame = new GLFrame(gl_env_ptr);
104  if (frame->InitWithExternalTexture()) {
105    return ToJBool(WrapObjectInJava(frame, env, thiz, true));
106  } else {
107    delete frame;
108    return JNI_FALSE;
109  }
110}
111
112jboolean Java_android_filterfw_core_GLFrame_deallocate(JNIEnv* env, jobject thiz) {
113  return ToJBool(DeleteNativeObject<GLFrame>(env, thiz));
114}
115
116jboolean Java_android_filterfw_core_GLFrame_setNativeData(JNIEnv* env,
117                                                          jobject thiz,
118                                                          jbyteArray data,
119                                                          jint offset,
120                                                          jint length) {
121  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
122  if (frame && data) {
123    jbyte* bytes = env->GetByteArrayElements(data, NULL);
124    if (bytes) {
125      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(bytes + offset), length);
126      env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
127      return ToJBool(success);
128    }
129  }
130  return JNI_FALSE;
131}
132
133jbyteArray Java_android_filterfw_core_GLFrame_getNativeData(JNIEnv* env, jobject thiz) {
134  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
135  if (frame && frame->Size() > 0) {
136    jbyteArray result = env->NewByteArray(frame->Size());
137    jbyte* data = env->GetByteArrayElements(result, NULL);
138    frame->CopyDataTo(reinterpret_cast<uint8_t*>(data), frame->Size());
139    env->ReleaseByteArrayElements(result, data, 0);
140    return result;
141  }
142  return NULL;
143}
144
145jboolean Java_android_filterfw_core_GLFrame_setNativeInts(JNIEnv* env,
146                                                          jobject thiz,
147                                                          jintArray ints) {
148  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
149  if (frame && ints) {
150    jint* int_ptr = env->GetIntArrayElements(ints, NULL);
151    const int length = env->GetArrayLength(ints);
152    if (int_ptr) {
153      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(int_ptr),
154                                            length * sizeof(jint));
155      env->ReleaseIntArrayElements(ints, int_ptr, JNI_ABORT);
156      return ToJBool(success);
157    }
158  }
159  return JNI_FALSE;
160}
161
162jintArray Java_android_filterfw_core_GLFrame_getNativeInts(JNIEnv* env, jobject thiz) {
163  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
164  if (frame && frame->Size() > 0 && (frame->Size() % sizeof(jint) == 0)) {
165    jintArray result = env->NewIntArray(frame->Size() / sizeof(jint));
166    jint* data = env->GetIntArrayElements(result, NULL);
167    frame->CopyDataTo(reinterpret_cast<uint8_t*>(data), frame->Size());
168    env->ReleaseIntArrayElements(result, data, 0);
169    return result;
170   }
171   return NULL;
172}
173
174jboolean Java_android_filterfw_core_GLFrame_setNativeFloats(JNIEnv* env,
175                                                            jobject thiz,
176                                                            jfloatArray floats) {
177  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
178  if (frame && floats) {
179    jfloat* float_ptr = env->GetFloatArrayElements(floats, NULL);
180    const int length = env->GetArrayLength(floats);
181    if (float_ptr) {
182      // Convert floats to RGBA buffer
183      uint8_t* rgba_buffer = new uint8_t[length];
184      ConvertFloatsToRGBA(float_ptr, length, rgba_buffer);
185      env->ReleaseFloatArrayElements(floats, float_ptr, JNI_ABORT);
186
187      // Write RGBA buffer to frame
188      const bool success = frame->WriteData(rgba_buffer, length);
189
190      // Clean-up
191      delete[] rgba_buffer;
192      return ToJBool(success);
193    }
194  }
195  return JNI_FALSE;
196}
197
198jfloatArray Java_android_filterfw_core_GLFrame_getNativeFloats(JNIEnv* env, jobject thiz) {
199  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
200  if (frame && frame->Size() > 0) {
201    // Create the result array
202    jfloatArray result = env->NewFloatArray(frame->Size());
203    jfloat* float_array = env->GetFloatArrayElements(result, NULL);
204
205    // Read the frame pixels
206    uint8_t* pixels = new uint8_t[frame->Size()];
207    frame->CopyDataTo(pixels, frame->Size());
208
209    // Convert them to floats
210    ConvertRGBAToFloats(pixels, frame->Size(), float_array);
211
212    // Clean-up
213    delete[] pixels;
214    env->ReleaseFloatArrayElements(result, float_array, 0);
215    return result;
216  }
217  return NULL;
218}
219
220jboolean Java_android_filterfw_core_GLFrame_setNativeBitmap(JNIEnv* env,
221                                                            jobject thiz,
222                                                            jobject bitmap,
223                                                            jint size) {
224  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
225  if (frame && bitmap) {
226    uint8_t* pixels;
227    const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&pixels));
228    if (result == ANDROID_BITMAP_RESUT_SUCCESS) {
229      const bool success = frame->WriteData(pixels, size);
230      return ToJBool(success &&
231                     AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESUT_SUCCESS);
232    }
233  }
234  return JNI_FALSE;
235}
236
237jboolean Java_android_filterfw_core_GLFrame_getNativeBitmap(JNIEnv* env,
238                                                            jobject thiz,
239                                                            jobject bitmap) {
240  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
241  if (frame && bitmap) {
242    uint8_t* pixels;
243    const int result = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void**>(&pixels));
244    if (result == ANDROID_BITMAP_RESUT_SUCCESS) {
245      frame->CopyDataTo(pixels, frame->Size());
246      return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESUT_SUCCESS);
247    }
248  }
249  return JNI_FALSE;
250}
251
252jboolean Java_android_filterfw_core_GLFrame_setNativeViewport(JNIEnv* env,
253                                                              jobject thiz,
254                                                              jint x,
255                                                              jint y,
256                                                              jint width,
257                                                              jint height) {
258  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
259  return frame ? ToJBool(frame->SetViewport(x, y, width, height)) : JNI_FALSE;
260}
261
262jint Java_android_filterfw_core_GLFrame_getNativeTextureId(JNIEnv* env, jobject thiz) {
263  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
264  return frame ? frame->GetTextureId() : -1;
265}
266
267jint Java_android_filterfw_core_GLFrame_getNativeFboId(JNIEnv* env, jobject thiz) {
268  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
269  return frame ? frame->GetFboId() : -1;
270}
271
272jboolean Java_android_filterfw_core_GLFrame_generateNativeMipMap(JNIEnv* env, jobject thiz) {
273  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
274  return frame ? ToJBool(frame->GenerateMipMap()) : JNI_FALSE;
275}
276
277jboolean Java_android_filterfw_core_GLFrame_setNativeTextureParam(JNIEnv* env,
278                                                                  jobject thiz,
279                                                                  jint param,
280                                                                  jint value) {
281  GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
282  return frame ? ToJBool(frame->SetTextureParameter(param, value)) : JNI_FALSE;
283}
284
285jboolean Java_android_filterfw_core_GLFrame_nativeCopyFromNative(JNIEnv* env,
286                                                                 jobject thiz,
287                                                                 jobject frame) {
288  GLFrame* this_frame = ConvertFromJava<GLFrame>(env, thiz);
289  NativeFrame* other_frame = ConvertFromJava<NativeFrame>(env, frame);
290  if (this_frame && other_frame) {
291    return ToJBool(this_frame->WriteData(other_frame->Data(), other_frame->Size()));
292  }
293  return JNI_FALSE;
294}
295
296jboolean Java_android_filterfw_core_GLFrame_nativeCopyFromGL(JNIEnv* env,
297                                                             jobject thiz,
298                                                             jobject frame) {
299  GLFrame* this_frame = ConvertFromJava<GLFrame>(env, thiz);
300  GLFrame* other_frame = ConvertFromJava<GLFrame>(env, frame);
301  if (this_frame && other_frame) {
302    return ToJBool(this_frame->CopyPixelsFrom(other_frame));
303  }
304  return JNI_FALSE;
305}
306
307jboolean Java_android_filterfw_core_GLFrame_nativeFocus(JNIEnv* env, jobject thiz) {
308    GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
309    return ToJBool(frame && frame->FocusFrameBuffer());
310}
311