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