130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni/*
230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Copyright (C) 2011 The Android Open Source Project
330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Licensed under the Apache License, Version 2.0 (the "License");
530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * you may not use this file except in compliance with the License.
630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * You may obtain a copy of the License at
730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *      http://www.apache.org/licenses/LICENSE-2.0
930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
1030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Unless required by applicable law or agreed to in writing, software
1130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * distributed under the License is distributed on an "AS IS" BASIS,
1230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * See the License for the specific language governing permissions and
1430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * limitations under the License.
1530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */
16f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi// #define LOG_NDEBUG 0
1730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include <stdint.h>
1930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include <android/native_window_jni.h>
2030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "jni/jni_gl_environment.h"
2230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "jni/jni_util.h"
2384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi#include <media/mediarecorder.h>
2430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "native/core/gl_env.h"
2530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi#include <gui/ISurfaceTexture.h>
2784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi#include <gui/SurfaceTextureClient.h>
28f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi#include <utils/Errors.h>
29f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi#include <system/window.h>
30f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi
3184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
3230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniusing android::filterfw::GLEnv;
3330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniusing android::filterfw::WindowHandle;
3484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiusing android::MediaRecorder;
3584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiusing android::sp;
3684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiusing android::ISurfaceTexture;
3784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketiusing android::SurfaceTextureClient;
3884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniclass NativeWindowHandle : public WindowHandle {
4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  public:
4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    NativeWindowHandle(ANativeWindow* window) : window_(window) {
4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    virtual ~NativeWindowHandle() {
4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
4730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    virtual void Destroy() {
4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      LOGI("Releasing ANativeWindow!");
5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      ANativeWindow_release(window_);
5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    virtual const void* InternalHandle() const {
5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return window_;
5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
575b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala    virtual void* InternalHandle() {
585b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala      return window_;
595b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala    }
605b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala
6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  private:
6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    ANativeWindow* window_;
6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni};
6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
65edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeAllocate(JNIEnv* env, jobject thiz) {
6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return ToJBool(WrapObjectInJava(new GLEnv(), env, thiz, true));
6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
69edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeDeallocate(JNIEnv* env, jobject thiz) {
7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return ToJBool(DeleteNativeObject<GLEnv>(env, thiz));
7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
7230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
73edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeInitWithNewContext(JNIEnv* env,
74edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala                                                                           jobject thiz) {
7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return gl_env ? ToJBool(gl_env->InitWithNewContext()) : JNI_FALSE;
7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
79edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeInitWithCurrentContext(JNIEnv* env,
80edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvala                                                                               jobject thiz) {
8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return gl_env ? ToJBool(gl_env->InitWithCurrentContext()) : JNI_FALSE;
8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
853fe79927824090988e0123781bec44f8a31779f8Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeIsActive(JNIEnv* env, jobject thiz) {
863fe79927824090988e0123781bec44f8a31779f8Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
873fe79927824090988e0123781bec44f8a31779f8Marius Renn  return gl_env ? ToJBool(gl_env->IsActive()) : JNI_FALSE;
883fe79927824090988e0123781bec44f8a31779f8Marius Renn}
893fe79927824090988e0123781bec44f8a31779f8Marius Renn
90a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeIsContextActive(JNIEnv* env, jobject thiz) {
91a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
92a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn  return gl_env ? ToJBool(gl_env->IsContextActive()) : JNI_FALSE;
93a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn}
94a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn
95a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Rennjboolean Java_android_filterfw_core_GLEnvironment_nativeIsAnyContextActive(JNIEnv* env,
96a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn                                                                           jclass clazz) {
97a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn  return ToJBool(GLEnv::IsAnyContextActive());
98a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn}
99a935c0d2759dc11fc60e56d0b2751e8eaa0fac74Marius Renn
100edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeActivate(JNIEnv* env, jobject thiz) {
10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return gl_env ? ToJBool(gl_env->Activate()) : JNI_FALSE;
10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
105edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeDeactivate(JNIEnv* env, jobject thiz) {
10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return gl_env ? ToJBool(gl_env->Deactivate()) : JNI_FALSE;
10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
110edfc0941e7a9480d2bbc70e842015e6fa56a2c3fEddy Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeSwapBuffers(JNIEnv* env, jobject thiz) {
11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return gl_env ? ToJBool(gl_env->SwapBuffers()) : JNI_FALSE;
11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
11584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// Get the native mediarecorder object corresponding to the java object
11684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketistatic sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject jmediarecorder) {
11784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    jclass clazz = env->FindClass("android/media/MediaRecorder");
11884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (clazz == NULL) {
11984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        return NULL;
12084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
12184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
12284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    jfieldID context = env->GetFieldID(clazz, "mNativeContext", "I");
12384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (context == NULL) {
12484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        return NULL;
12584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
12684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
12784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    MediaRecorder* const p = (MediaRecorder*)env->GetIntField(jmediarecorder, context);
12884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    env->DeleteLocalRef(clazz);
12984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    return sp<MediaRecorder>(p);
13084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi}
13184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
13284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
13330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronijint Java_android_filterfw_core_GLEnvironment_nativeAddSurface(JNIEnv* env,
13430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                               jobject thiz,
13530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                               jobject surface) {
13630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
13730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  if (!surface) {
13830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    LOGE("GLEnvironment: Null Surface passed!");
13930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    return -1;
14030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  } else if (gl_env) {
14130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Get the ANativeWindow
14230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
14330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    if (!window) {
14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      LOGE("GLEnvironment: Error creating window!");
14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return -1;
14630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
14730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
14830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    NativeWindowHandle* winHandle = new NativeWindowHandle(window);
14930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    int result = gl_env->FindSurfaceIdForWindow(winHandle);
15030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    if (result == -1) {
15130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      // Configure surface
15230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      EGLConfig config;
15330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      EGLint numConfigs = -1;
15430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      EGLint configAttribs[] = {
15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
15630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
157f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_RED_SIZE, 8,
158f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_GREEN_SIZE, 8,
159f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_BLUE_SIZE, 8,
160f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_RECORDABLE_ANDROID, EGL_TRUE,
16130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        EGL_NONE
16230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      };
16330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
164f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi
165f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi
16630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      if (numConfigs < 1) {
16830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        LOGE("GLEnvironment: No suitable EGL configuration found for surface!");
16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return -1;
17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      }
17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
17230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      // Create the EGL surface
17330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                      config,
17530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                      window,
17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                      NULL);
17730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        LOGE("GLEnvironment: Error creating window surface!");
18017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        return -1;
18117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      }
18217b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
18317b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      // Add it to GL Env and assign ID
18417b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      result = gl_env->AddWindowSurface(egl_surface, winHandle);
18517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    } else {
18617b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      delete winHandle;
18717b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    }
18817b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    return result;
18917b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala  }
19017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala  return -1;
19117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala}
19217b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
19317b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvalajint Java_android_filterfw_core_GLEnvironment_nativeAddSurfaceTexture(JNIEnv* env,
19417b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                                      jobject thiz,
19517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                                      jobject surfaceTexture,
19617b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                                      jint width,
19717b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                                      jint height) {
19817b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
19917b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala  if (!surfaceTexture) {
20017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    LOGE("GLEnvironment: Null SurfaceTexture passed!");
20117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    return -1;
20217b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala  } else if (gl_env) {
20317b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    // Get the ANativeWindow
20417b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    ANativeWindow* window = ANativeWindow_fromSurfaceTexture(env, surfaceTexture);
20517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    if (!window) {
20617b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      LOGE("GLEnvironment: Error creating window!");
20717b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      return -1;
20817b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    }
20917b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
21017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    // Don't care about format (will get overridden by SurfaceTexture
21117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    // anyway), but do care about width and height
21284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // TODO: Probably, this should be just be
21384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // ANativeWindow_setBuffersDimensions. The pixel format is
21484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // set during the eglCreateWindowSurface
21517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    ANativeWindow_setBuffersGeometry(window, width, height, 0);
21617b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
21717b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    NativeWindowHandle* winHandle = new NativeWindowHandle(window);
21817b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    int result = gl_env->FindSurfaceIdForWindow(winHandle);
21917b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala    if (result == -1) {
22017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      // Configure surface
22117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      EGLConfig config;
22217b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      EGLint numConfigs = -1;
22317b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      EGLint configAttribs[] = {
22417b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
22517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
226f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_RED_SIZE, 8,
227f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_GREEN_SIZE, 8,
228f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_BLUE_SIZE, 8,
229f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi        EGL_RECORDABLE_ANDROID, EGL_TRUE,
23017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        EGL_NONE
23117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      };
23217b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
233f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi
234f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi
23517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
23617b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      if (numConfigs < 1) {
23717b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        LOGE("GLEnvironment: No suitable EGL configuration found for surface texture!");
23817b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        return -1;
23917b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      }
24017b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
24117b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      // Create the EGL surface
24217b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
24317b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                      config,
24417b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                      window,
24517b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala                                                      NULL);
24617b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala
24717b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala      if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
24817b672fd95a037fefb3e06c2f214551a45a15954Eino-Ville Talvala        LOGE("GLEnvironment: Error creating window surface!");
24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return -1;
25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      }
25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      // Add it to GL Env and assign ID
25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      result = gl_env->AddWindowSurface(egl_surface, winHandle);
25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    } else {
25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      delete winHandle;
25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    return result;
25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  }
25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return -1;
26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
26284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// nativeAddSurfaceFromMediaRecorder gets an EGLSurface
26384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// using a MediaRecorder object.
26484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// When Mediarecorder is used for recording GL Frames, it
26584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// will have a reference to a Native Handle (a SurfaceTexureClient)
26684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// which talks to the StageFrightRecorder in mediaserver via
26784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi// a binder interface.
26884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketijint Java_android_filterfw_core_GLEnvironment_nativeAddSurfaceFromMediaRecorder(
26984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                      JNIEnv* env,
27084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                      jobject thiz,
27184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                      jobject jmediarecorder) {
272f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi    LOGV("GLEnv Jni: nativeAddSurfaceFromMediaRecorder");
27384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
27484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (!gl_env) {
27584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        return -1;
27684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
27784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // get a native mediarecorder object from the java object
27884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    sp<MediaRecorder> mr = getMediaRecorder(env, jmediarecorder);
27984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (mr == NULL) {
28084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        LOGE("GLEnvironment: Error- MediaRecorder could not be initialized!");
28184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        return -1;
28284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
28384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
28484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // Ask the mediarecorder to return a handle to a surfacemediasource
28584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // This will talk to the StageFrightRecorder via MediaRecorderClient
28684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // over binder calls
28784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    sp<ISurfaceTexture> surfaceMS = mr->querySurfaceMediaSourceFromMediaServer();
28884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (surfaceMS == NULL) {
28984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      LOGE("GLEnvironment: Error- MediaRecorder returned a null \
29084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi              <ISurfaceTexture> handle.");
29184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      return -1;
29284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
29384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    sp<SurfaceTextureClient> surfaceTC = new SurfaceTextureClient(surfaceMS);
29484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // Get the ANativeWindow
29584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    sp<ANativeWindow> window = surfaceTC;
29684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
29784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
29884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (window == NULL) {
29984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      LOGE("GLEnvironment: Error creating window!");
30084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      return -1;
30184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
302f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi    window->incStrong((void*)ANativeWindow_acquire);
30384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
30484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // In case of encoding, no need to set the dimensions
30584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // on the buffers. The dimensions for the final encoding are set by
30684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // the consumer side.
30784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // The pixel format is dictated by the GL, and set during the
30884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // eglCreateWindowSurface
30984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
31084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    NativeWindowHandle* winHandle = new NativeWindowHandle(window.get());
31184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    int result = gl_env->FindSurfaceIdForWindow(winHandle);
31284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // If we find a surface with that window handle, just return that id
31384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (result != -1) {
31484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        delete winHandle;
31584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi        return result;
31684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
31784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // If we do not find a surface with that window handle, create
31884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // one and assign to it the handle
31984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // Configure surface
32084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    EGLConfig config;
32184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    EGLint numConfigs = -1;
32284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    EGLint configAttribs[] = {
32384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi          EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
32484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi          EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
32584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi          EGL_RED_SIZE, 8,
32684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi          EGL_GREEN_SIZE, 8,
32784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi          EGL_BLUE_SIZE, 8,
328f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi          EGL_RECORDABLE_ANDROID, EGL_TRUE,
32984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi          EGL_NONE
33084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    };
33184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
332f283a907a88fc348b770186562c7a1046a8b7367Pannag Sanketi
33384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    eglChooseConfig(gl_env->display(), configAttribs, &config, 1, &numConfigs);
33484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (numConfigs < 1) {
33584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      LOGE("GLEnvironment: No suitable EGL configuration found for surface texture!");
33684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      delete winHandle;
33784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      return -1;
33884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
33984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
34084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // Create the EGL surface
34184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    EGLSurface egl_surface = eglCreateWindowSurface(gl_env->display(),
34284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                    config,
34384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                    window.get(),
34484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi                                                    NULL);
34584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
34684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    if (GLEnv::CheckEGLError("eglCreateWindowSurface")) {
34784a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      LOGE("GLEnvironment: Error creating window surface!");
34884a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      delete winHandle;
34984a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi      return -1;
35084a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    }
35184a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
35284a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    // Add it to GL Env and assign ID
35384a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    result = gl_env->AddWindowSurface(egl_surface, winHandle);
35484a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi    return result;
35584a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi}
35684a9fb79433ee7c66fe1df7b0a754828ff89aec1Pannag Sanketi
35730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronijboolean Java_android_filterfw_core_GLEnvironment_nativeActivateSurfaceId(JNIEnv* env,
35830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                                          jobject thiz,
35930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                                          jint surfaceId) {
36030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
361470dfeec8a0fbae2a0e8f6021660ef66135b22cePannag Sanketi  return gl_env ? ToJBool(gl_env->SwitchToSurfaceId(surfaceId) && gl_env->Activate()) : JNI_FALSE;
36230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
36330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
36430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronijboolean Java_android_filterfw_core_GLEnvironment_nativeRemoveSurfaceId(JNIEnv* env,
36530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                                        jobject thiz,
36630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                                                        jint surfaceId) {
36730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
36830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return gl_env ? ToJBool(gl_env->ReleaseSurfaceId(surfaceId)) : JNI_FALSE;
36930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
3705b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala
3715b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvalajboolean Java_android_filterfw_core_GLEnvironment_nativeSetSurfaceTimestamp(JNIEnv* env,
3725b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala                                                                            jobject thiz,
3735b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala                                                                            jlong timestamp) {
3745b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala  GLEnv* gl_env = ConvertFromJava<GLEnv>(env, thiz);
3755b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala  int64_t timestamp_native = timestamp;
3765b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala  return gl_env ? ToJBool(gl_env->SetSurfaceTimestamp(timestamp_native)) : JNI_FALSE;
3775b9eb6d686c439545dafcc8e25e9e3747281c3deEino-Ville Talvala}
378