blob: 5f007396f2878a9d7c35cf85d4568164f1309a6a [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// #define LOG_NDEBUG 0
17
18#include <stdint.h>
19#include <android/native_window_jni.h>
20
21#include "jni/jni_gl_environment.h"
22#include "jni/jni_util.h"
Marius Renn65953da2012-03-27 10:44:45 -070023#include "native/core/gl_env.h"
Andreas Gampee5160e72014-11-10 17:49:02 -080024#include <media/mediarecorder.h>
Marius Renn65953da2012-03-27 10:44:45 -070025
Andy McFaddend47f7d82012-12-18 09:48:38 -080026#include <gui/IGraphicBufferProducer.h>
Mathias Agopian52800612013-02-14 17:11:20 -080027#include <gui/Surface.h>
Marius Renn65953da2012-03-27 10:44:45 -070028#include <utils/Errors.h>
29#include <system/window.h>
30
31
32using android::filterfw::GLEnv;
33using android::filterfw::WindowHandle;
34using android::MediaRecorder;
35using android::sp;
Andy McFaddend47f7d82012-12-18 09:48:38 -080036using android::IGraphicBufferProducer;
Mathias Agopian52800612013-02-14 17:11:20 -080037using android::Surface;
Marius Renn65953da2012-03-27 10:44:45 -070038
39
40class NativeWindowHandle : public WindowHandle {
41 public:
42 NativeWindowHandle(ANativeWindow* window) : window_(window) {
43 }
44
45 virtual ~NativeWindowHandle() {
46 }
47
48 virtual void Destroy() {
49 ALOGI("Releasing ANativeWindow!");
50 ANativeWindow_release(window_);
51 }
52
53 virtual const void* InternalHandle() const {
54 return window_;
55 }
56
57 virtual void* InternalHandle() {
58 return window_;
59 }
60
61 private:
62 ANativeWindow* window_;
63};
64
65jboolean Java_android_filterfw_core_GLEnvironment_nativeAllocate(JNIEnv* env, jobject thiz) {
66 return ToJBool(WrapObjectInJava(new GLEnv(), env, thiz, true));
67}
68
69jboolean Java_android_filterfw_core_GLEnvironment_nativeDeallocate(JNIEnv* env, jobject thiz) {
70 return ToJBool(DeleteNativeObject<GLEnv>(env, thiz));
71}
72
73jboolean Java_android_filterfw_core_GLEnvironment_nativeInitWithNewContext(JNIEnv* env,
74 jobject thiz) {
75 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
76 return gl_env ? ToJBool(gl_env->InitWithNewContext()) : JNI_FALSE;
77}
78
79jboolean Java_android_filterfw_core_GLEnvironment_nativeInitWithCurrentContext(JNIEnv* env,
80 jobject thiz) {
81 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
82 return gl_env ? ToJBool(gl_env->InitWithCurrentContext()) : JNI_FALSE;
83}
84
85jboolean Java_android_filterfw_core_GLEnvironment_nativeIsActive(JNIEnv* env, jobject thiz) {
86 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
87 return gl_env ? ToJBool(gl_env->IsActive()) : JNI_FALSE;
88}
89
90jboolean Java_android_filterfw_core_GLEnvironment_nativeIsContextActive(JNIEnv* env, jobject thiz) {
91 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
92 return gl_env ? ToJBool(gl_env->IsContextActive()) : JNI_FALSE;
93}
94
Andreas Gampee5160e72014-11-10 17:49:02 -080095jboolean Java_android_filterfw_core_GLEnvironment_nativeIsAnyContextActive(JNIEnv* /* env */,
96 jclass /* clazz */) {
Marius Renn65953da2012-03-27 10:44:45 -070097 return ToJBool(GLEnv::IsAnyContextActive());
98}
99
100jboolean Java_android_filterfw_core_GLEnvironment_nativeActivate(JNIEnv* env, jobject thiz) {
101 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
102 return gl_env ? ToJBool(gl_env->Activate()) : JNI_FALSE;
103}
104
105jboolean Java_android_filterfw_core_GLEnvironment_nativeDeactivate(JNIEnv* env, jobject thiz) {
106 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
107 return gl_env ? ToJBool(gl_env->Deactivate()) : JNI_FALSE;
108}
109
110jboolean Java_android_filterfw_core_GLEnvironment_nativeSwapBuffers(JNIEnv* env, jobject thiz) {
111 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
112 return gl_env ? ToJBool(gl_env->SwapBuffers()) : JNI_FALSE;
113}
114
115// Get the native mediarecorder object corresponding to the java object
116static sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject jmediarecorder) {
117 jclass clazz = env->FindClass("android/media/MediaRecorder");
118 if (clazz == NULL) {
119 return NULL;
120 }
121
Ashok Bhat075e9a12014-01-06 13:45:09 +0000122 jfieldID context = env->GetFieldID(clazz, "mNativeContext", "J");
Marius Renn65953da2012-03-27 10:44:45 -0700123 if (context == NULL) {
124 return NULL;
125 }
126
Ashok Bhat075e9a12014-01-06 13:45:09 +0000127 MediaRecorder* const p = (MediaRecorder*)env->GetLongField(jmediarecorder, context);
Marius Renn65953da2012-03-27 10:44:45 -0700128 env->DeleteLocalRef(clazz);
129 return sp<MediaRecorder>(p);
130}
131
132
133jint Java_android_filterfw_core_GLEnvironment_nativeAddSurface(JNIEnv* env,
134 jobject thiz,
135 jobject surface) {
136 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
137 if (!surface) {
138 ALOGE("GLEnvironment: Null Surface passed!");
139 return -1;
140 } else if (gl_env) {
141 // Get the ANativeWindow
142 ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
143 if (!window) {
144 ALOGE("GLEnvironment: Error creating window!");
145 return -1;
146 }
147
148 NativeWindowHandle* winHandle = new NativeWindowHandle(window);
149 int result = gl_env->FindSurfaceIdForWindow(winHandle);
150 if (result == -1) {
151 // Configure surface
152 EGLConfig config;
153 EGLint numConfigs = -1;
154 EGLint configAttribs[] = {
155 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
156 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
157 EGL_RED_SIZE, 8,
158 EGL_GREEN_SIZE, 8,
159 EGL_BLUE_SIZE, 8,
160 EGL_RECORDABLE_ANDROID, EGL_TRUE,
161 EGL_NONE
162 };
163
164
165
166 eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
167 if (numConfigs < 1) {
168 ALOGE("GLEnvironment: No suitable EGL configuration found for surface!");
169 return -1;
170 }
171
172 // Create the EGL surface
173 EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
174 config,
175 window,
176 NULL);
177
178 if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
179 ALOGE("GLEnvironment: Error creating window surface!");
180 return -1;
181 }
182
183 // Add it to GL Env and assign ID
184 result = gl_env->AddWindowSurface(egl_surface, winHandle);
185 } else {
186 delete winHandle;
187 }
188 return result;
189 }
190 return -1;
191}
192
193jint Java_android_filterfw_core_GLEnvironment_nativeAddSurfaceWidthHeight(JNIEnv* env,
194 jobject thiz,
195 jobject surface,
196 jint width,
197 jint height) {
198 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
199 if (!surface) {
200 ALOGE("GLEnvironment: Null SurfaceTexture passed!");
201 return -1;
202 } else if (gl_env) {
203 // Get the ANativeWindow
204 ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
205 if (!window) {
206 ALOGE("GLEnvironment: Error creating window!");
207 return -1;
208 }
209
210 // Don't care about format (will get overridden by SurfaceTexture
211 // anyway), but do care about width and height
212 // TODO: Probably, this should be just be
213 // ANativeWindow_setBuffersDimensions. The pixel format is
214 // set during the eglCreateWindowSurface
215 ANativeWindow_setBuffersGeometry(window, width, height, 0);
216
217 NativeWindowHandle* winHandle = new NativeWindowHandle(window);
218 int result = gl_env->FindSurfaceIdForWindow(winHandle);
219 if (result == -1) {
220 // Configure surface
221 EGLConfig config;
222 EGLint numConfigs = -1;
223 EGLint configAttribs[] = {
224 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
225 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
226 EGL_RED_SIZE, 8,
227 EGL_GREEN_SIZE, 8,
228 EGL_BLUE_SIZE, 8,
229 EGL_RECORDABLE_ANDROID, EGL_TRUE,
230 EGL_NONE
231 };
232
233
234
235 eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
236 if (numConfigs < 1) {
237 ALOGE("GLEnvironment: No suitable EGL configuration found for surface texture!");
238 return -1;
239 }
240
241 // Create the EGL surface
242 EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
243 config,
244 window,
245 NULL);
246
247 if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
248 ALOGE("GLEnvironment: Error creating window surface!");
249 return -1;
250 }
251
252 // Add it to GL Env and assign ID
253 result = gl_env->AddWindowSurface(egl_surface, winHandle);
254 } else {
255 delete winHandle;
256 }
257 return result;
258 }
259 return -1;
260}
261
262// nativeAddSurfaceFromMediaRecorder gets an EGLSurface
263// using a MediaRecorder object.
264// When Mediarecorder is used for recording GL Frames, it
265// will have a reference to a Native Handle (a SurfaceTexureClient)
266// which talks to the StageFrightRecorder in mediaserver via
267// a binder interface.
268jint Java_android_filterfw_core_GLEnvironment_nativeAddSurfaceFromMediaRecorder(
269 JNIEnv* env,
270 jobject thiz,
271 jobject jmediarecorder) {
272 ALOGV("GLEnv Jni: nativeAddSurfaceFromMediaRecorder");
273 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
274 if (!gl_env) {
275 return -1;
276 }
277 // get a native mediarecorder object from the java object
278 sp<MediaRecorder> mr = getMediaRecorder(env, jmediarecorder);
279 if (mr == NULL) {
280 ALOGE("GLEnvironment: Error- MediaRecorder could not be initialized!");
281 return -1;
282 }
283
284 // Ask the mediarecorder to return a handle to a surfacemediasource
285 // This will talk to the StageFrightRecorder via MediaRecorderClient
286 // over binder calls
Andy McFaddend47f7d82012-12-18 09:48:38 -0800287 sp<IGraphicBufferProducer> surfaceMS = mr->querySurfaceMediaSourceFromMediaServer();
Marius Renn65953da2012-03-27 10:44:45 -0700288 if (surfaceMS == NULL) {
289 ALOGE("GLEnvironment: Error- MediaRecorder returned a null \
Andy McFaddend47f7d82012-12-18 09:48:38 -0800290 <IGraphicBufferProducer> handle.");
Marius Renn65953da2012-03-27 10:44:45 -0700291 return -1;
292 }
Mathias Agopian52800612013-02-14 17:11:20 -0800293 sp<Surface> surfaceTC = new Surface(surfaceMS);
Marius Renn65953da2012-03-27 10:44:45 -0700294 // Get the ANativeWindow
295 sp<ANativeWindow> window = surfaceTC;
296
297
298 if (window == NULL) {
299 ALOGE("GLEnvironment: Error creating window!");
300 return -1;
301 }
302 window->incStrong((void*)ANativeWindow_acquire);
303
304 // In case of encoding, no need to set the dimensions
305 // on the buffers. The dimensions for the final encoding are set by
306 // the consumer side.
307 // The pixel format is dictated by the GL, and set during the
308 // eglCreateWindowSurface
309
310 NativeWindowHandle* winHandle = new NativeWindowHandle(window.get());
311 int result = gl_env->FindSurfaceIdForWindow(winHandle);
312 // If we find a surface with that window handle, just return that id
313 if (result != -1) {
314 delete winHandle;
315 return result;
316 }
317 // If we do not find a surface with that window handle, create
318 // one and assign to it the handle
319 // Configure surface
320 EGLConfig config;
321 EGLint numConfigs = -1;
322 EGLint configAttribs[] = {
323 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
324 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
325 EGL_RED_SIZE, 8,
326 EGL_GREEN_SIZE, 8,
327 EGL_BLUE_SIZE, 8,
328 EGL_RECORDABLE_ANDROID, EGL_TRUE,
329 EGL_NONE
330 };
331
332
333 eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
334 if (numConfigs < 1) {
335 ALOGE("GLEnvironment: No suitable EGL configuration found for surface texture!");
336 delete winHandle;
337 return -1;
338 }
339
340 // Create the EGL surface
341 EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
342 config,
343 window.get(),
344 NULL);
345
346 if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
347 ALOGE("GLEnvironment: Error creating window surface!");
348 delete winHandle;
349 return -1;
350 }
351
352 // Add it to GL Env and assign ID
353 result = gl_env->AddWindowSurface(egl_surface, winHandle);
354 return result;
355}
356
357jboolean Java_android_filterfw_core_GLEnvironment_nativeActivateSurfaceId(JNIEnv* env,
358 jobject thiz,
359 jint surfaceId) {
360 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
361 return gl_env ? ToJBool(gl_env->SwitchToSurfaceId(surfaceId) && gl_env->Activate()) : JNI_FALSE;
362}
363
364jboolean Java_android_filterfw_core_GLEnvironment_nativeRemoveSurfaceId(JNIEnv* env,
365 jobject thiz,
366 jint surfaceId) {
367 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
368 return gl_env ? ToJBool(gl_env->ReleaseSurfaceId(surfaceId)) : JNI_FALSE;
369}
370
371jboolean Java_android_filterfw_core_GLEnvironment_nativeSetSurfaceTimestamp(JNIEnv* env,
372 jobject thiz,
373 jlong timestamp) {
374 GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
375 int64_t timestamp_native = timestamp;
376 return gl_env ? ToJBool(gl_env->SetSurfaceTimestamp(timestamp_native)) : JNI_FALSE;
377}