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   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 
     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 
     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 
     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 
    100 jboolean Java_android_filterfw_core_GLFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
    101   return ToJBool(DeleteNativeObject<GLFrame>(env, thiz));
    102 }
    103 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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