165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// #define LOG_NDEBUG 0
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <stdint.h>
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <android/native_window_jni.h>
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "jni/jni_gl_environment.h"
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "jni/jni_util.h"
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <media/mediarecorder.h>
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "native/core/gl_env.h"
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <gui/ISurfaceTexture.h>
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <gui/SurfaceTextureClient.h>
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <utils/Errors.h>
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <system/window.h>
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::filterfw::GLEnv;
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::filterfw::WindowHandle;
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::MediaRecorder;
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::sp;
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::ISurfaceTexture;
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennusing android::SurfaceTextureClient;
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennclass NativeWindowHandle : public WindowHandle {
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  public:
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    NativeWindowHandle(ANativeWindow* window) : window_(window) {
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    virtual ~NativeWindowHandle() {
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    virtual void Destroy() {
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGI("Releasing ANativeWindow!");
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ANativeWindow_release(window_);
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    virtual const void* InternalHandle() const {
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return window_;
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    virtual void* InternalHandle() {
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return window_;
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  private:
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ANativeWindow* window_;
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn};
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeAllocate(JNIEnv* env, jobject thiz) {
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return ToJBool(WrapObjectInJava(new GLEnv(), env, thiz, true));
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeDeallocate(JNIEnv* env, jobject thiz) {
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return ToJBool(DeleteNativeObject<GLEnv>(env, thiz));
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeInitWithNewContext(JNIEnv* env,
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                           jobject thiz) {
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->InitWithNewContext()) : JNI_FALSE;
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeInitWithCurrentContext(JNIEnv* env,
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                               jobject thiz) {
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->InitWithCurrentContext()) : JNI_FALSE;
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeIsActive(JNIEnv* env, jobject thiz) {
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->IsActive()) : JNI_FALSE;
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeIsContextActive(JNIEnv* env, jobject thiz) {
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->IsContextActive()) : JNI_FALSE;
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeIsAnyContextActive(JNIEnv* env,
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                           jclass clazz) {
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return ToJBool(GLEnv::IsAnyContextActive());
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeActivate(JNIEnv* env, jobject thiz) {
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->Activate()) : JNI_FALSE;
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeDeactivate(JNIEnv* env, jobject thiz) {
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->Deactivate()) : JNI_FALSE;
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeSwapBuffers(JNIEnv* env, jobject thiz) {
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->SwapBuffers()) : JNI_FALSE;
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Get the native mediarecorder object corresponding to the java object
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstatic sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject jmediarecorder) {
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jclass clazz = env->FindClass("android/media/MediaRecorder");
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (clazz == NULL) {
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return NULL;
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    jfieldID context = env->GetFieldID(clazz, "mNativeContext", "I");
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (context == NULL) {
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return NULL;
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    MediaRecorder* const p = (MediaRecorder*)env->GetIntField(jmediarecorder, context);
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    env->DeleteLocalRef(clazz);
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return sp<MediaRecorder>(p);
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjint Java_android_filterfw_core_GLEnvironment_nativeAddSurface(JNIEnv* env,
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                               jobject thiz,
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                               jobject surface) {
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (!surface) {
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("GLEnvironment: Null Surface passed!");
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return -1;
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  } else if (gl_env) {
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Get the ANativeWindow
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (!window) {
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("GLEnvironment: Error creating window!");
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return -1;
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    NativeWindowHandle* winHandle = new NativeWindowHandle(window);
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    int result = gl_env->FindSurfaceIdForWindow(winHandle);
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (result == -1) {
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Configure surface
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLConfig config;
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLint numConfigs = -1;
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLint configAttribs[] = {
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_RED_SIZE, 8,
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_GREEN_SIZE, 8,
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_BLUE_SIZE, 8,
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_RECORDABLE_ANDROID, EGL_TRUE,
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_NONE
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      };
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (numConfigs < 1) {
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("GLEnvironment: No suitable EGL configuration found for surface!");
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return -1;
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Create the EGL surface
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      config,
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      window,
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      NULL);
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("GLEnvironment: Error creating window surface!");
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return -1;
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Add it to GL Env and assign ID
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      result = gl_env->AddWindowSurface(egl_surface, winHandle);
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    } else {
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      delete winHandle;
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return result;
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return -1;
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjint Java_android_filterfw_core_GLEnvironment_nativeAddSurfaceWidthHeight(JNIEnv* env,
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                      jobject thiz,
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                      jobject surface,
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                      jint width,
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                      jint height) {
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (!surface) {
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("GLEnvironment: Null SurfaceTexture passed!");
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return -1;
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  } else if (gl_env) {
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Get the ANativeWindow
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (!window) {
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("GLEnvironment: Error creating window!");
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return -1;
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Don't care about format (will get overridden by SurfaceTexture
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // anyway), but do care about width and height
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // TODO: Probably, this should be just be
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // ANativeWindow_setBuffersDimensions. The pixel format is
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // set during the eglCreateWindowSurface
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ANativeWindow_setBuffersGeometry(window, width, height, 0);
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    NativeWindowHandle* winHandle = new NativeWindowHandle(window);
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    int result = gl_env->FindSurfaceIdForWindow(winHandle);
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (result == -1) {
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Configure surface
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLConfig config;
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLint numConfigs = -1;
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLint configAttribs[] = {
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_RED_SIZE, 8,
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_GREEN_SIZE, 8,
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_BLUE_SIZE, 8,
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_RECORDABLE_ANDROID, EGL_TRUE,
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        EGL_NONE
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      };
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (numConfigs < 1) {
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("GLEnvironment: No suitable EGL configuration found for surface texture!");
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return -1;
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Create the EGL surface
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      config,
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      window,
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      NULL);
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("GLEnvironment: Error creating window surface!");
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return -1;
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      // Add it to GL Env and assign ID
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      result = gl_env->AddWindowSurface(egl_surface, winHandle);
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    } else {
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      delete winHandle;
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return result;
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return -1;
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// nativeAddSurfaceFromMediaRecorder gets an EGLSurface
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// using a MediaRecorder object.
26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// When Mediarecorder is used for recording GL Frames, it
26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// will have a reference to a Native Handle (a SurfaceTexureClient)
26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// which talks to the StageFrightRecorder in mediaserver via
26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// a binder interface.
26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjint Java_android_filterfw_core_GLEnvironment_nativeAddSurfaceFromMediaRecorder(
26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      JNIEnv* env,
27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      jobject thiz,
27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                      jobject jmediarecorder) {
27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGV("GLEnv Jni: nativeAddSurfaceFromMediaRecorder");
27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (!gl_env) {
27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return -1;
27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // get a native mediarecorder object from the java object
27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    sp<MediaRecorder> mr = getMediaRecorder(env, jmediarecorder);
27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (mr == NULL) {
28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("GLEnvironment: Error- MediaRecorder could not be initialized!");
28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return -1;
28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Ask the mediarecorder to return a handle to a surfacemediasource
28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // This will talk to the StageFrightRecorder via MediaRecorderClient
28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // over binder calls
28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    sp<ISurfaceTexture> surfaceMS = mr->querySurfaceMediaSourceFromMediaServer();
28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (surfaceMS == NULL) {
28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("GLEnvironment: Error- MediaRecorder returned a null \
29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn              <ISurfaceTexture> handle.");
29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return -1;
29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    sp<SurfaceTextureClient> surfaceTC = new SurfaceTextureClient(surfaceMS);
29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Get the ANativeWindow
29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    sp<ANativeWindow> window = surfaceTC;
29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (window == NULL) {
29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("GLEnvironment: Error creating window!");
30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return -1;
30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    window->incStrong((void*)ANativeWindow_acquire);
30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // In case of encoding, no need to set the dimensions
30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // on the buffers. The dimensions for the final encoding are set by
30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // the consumer side.
30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // The pixel format is dictated by the GL, and set during the
30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // eglCreateWindowSurface
30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
31065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    NativeWindowHandle* winHandle = new NativeWindowHandle(window.get());
31165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    int result = gl_env->FindSurfaceIdForWindow(winHandle);
31265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // If we find a surface with that window handle, just return that id
31365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (result != -1) {
31465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        delete winHandle;
31565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return result;
31665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
31765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // If we do not find a surface with that window handle, create
31865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // one and assign to it the handle
31965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Configure surface
32065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGLConfig config;
32165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGLint numConfigs = -1;
32265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGLint configAttribs[] = {
32365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
32465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
32565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_RED_SIZE, 8,
32665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_GREEN_SIZE, 8,
32765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_BLUE_SIZE, 8,
32865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_RECORDABLE_ANDROID, EGL_TRUE,
32965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          EGL_NONE
33065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    };
33165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
33265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
33365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
33465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (numConfigs < 1) {
33565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("GLEnvironment: No suitable EGL configuration found for surface texture!");
33665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      delete winHandle;
33765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return -1;
33865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
33965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
34065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Create the EGL surface
34165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
34265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                    config,
34365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                    window.get(),
34465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                    NULL);
34565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
34665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
34765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ALOGE("GLEnvironment: Error creating window surface!");
34865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      delete winHandle;
34965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return -1;
35065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
35165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
35265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Add it to GL Env and assign ID
35365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    result = gl_env->AddWindowSurface(egl_surface, winHandle);
35465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return result;
35565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
35665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
35765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeActivateSurfaceId(JNIEnv* env,
35865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                          jobject thiz,
35965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                          jint surfaceId) {
36065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
36165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->SwitchToSurfaceId(surfaceId) && gl_env->Activate()) : JNI_FALSE;
36265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
36365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
36465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeRemoveSurfaceId(JNIEnv* env,
36565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                        jobject thiz,
36665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                        jint surfaceId) {
36765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
36865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->ReleaseSurfaceId(surfaceId)) : JNI_FALSE;
36965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
37065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
37165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeSetSurfaceTimestamp(JNIEnv* env,
37265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                            jobject thiz,
37365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                                            jlong timestamp) {
37465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
37565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  int64_t timestamp_native = timestamp;
37665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return gl_env ? ToJBool(gl_env->SetSurfaceTimestamp(timestamp_native)) : JNI_FALSE;
37765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
378