blob: b55bc5d0ef715ae48eb584087e7db83873aeafc4 [file] [log] [blame]
Marius Renn65953da2012-03-27 10:44:45 -07001/*
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_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
60jboolean 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
77jboolean 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
94jboolean 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
108jboolean Java_android_filterfw_core_GLFrame_nativeDeallocate(JNIEnv* env, jobject thiz) {
109 return ToJBool(DeleteNativeObject<GLFrame>(env, thiz));
110}
111
112jboolean 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
129jbyteArray 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
141jboolean 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
158jintArray 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
170jboolean 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
194jfloatArray 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
216jboolean 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));
Andrew Hsieheba82542012-12-12 11:27:44 +0800224 if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
Marius Renn65953da2012-03-27 10:44:45 -0700225 const bool success = frame->WriteData(pixels, size);
226 return ToJBool(success &&
Andrew Hsieheba82542012-12-12 11:27:44 +0800227 AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
Marius Renn65953da2012-03-27 10:44:45 -0700228 }
229 }
230 return JNI_FALSE;
231}
232
233jboolean 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));
Andrew Hsieheba82542012-12-12 11:27:44 +0800240 if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
Marius Renn65953da2012-03-27 10:44:45 -0700241 frame->CopyDataTo(pixels, frame->Size());
Andrew Hsieheba82542012-12-12 11:27:44 +0800242 return (AndroidBitmap_unlockPixels(env, bitmap) == ANDROID_BITMAP_RESULT_SUCCESS);
Marius Renn65953da2012-03-27 10:44:45 -0700243 }
244 }
245 return JNI_FALSE;
246}
247
248jboolean 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
258jint 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
263jint 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
268jboolean 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
273jboolean 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
281jboolean 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
286jboolean 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
297jboolean 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
308jboolean 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
313jboolean 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
318jboolean 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