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