diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index d98957c62..e5f5ef79f 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -59,8 +59,15 @@ target_sources(
native-lib
PUBLIC
src/main/cpp/native-lib.cpp
+ src/main/cpp/BrowserEGLContext.cpp
)
+
+include(AndroidNdkModules)
+android_ndk_import_module_native_app_glue()
+target_link_libraries(native-lib native_app_glue)
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
endif()
+
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
diff --git a/app/build.gradle b/app/build.gradle
index f6ad104af..1413afb38 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -80,11 +80,23 @@ android {
]
}
+ googlevr {
+ java.srcDirs = [
+ 'src/common/nativeactivity'
+ ]
+ }
+
oculusvr {
+ java.srcDirs = [
+ 'src/common/nativeactivity'
+ ]
jniLibs.srcDirs = ["${project.rootDir}/third_party/ovr_mobile/VrApi/Libs"]
}
svr {
+ java.srcDirs = [
+ 'src/common/nativeactivity'
+ ]
jniLibs.srcDirs = ["${project.rootDir}/third_party/svr/libs"]
}
diff --git a/app/src/common/nativeactivity/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/nativeactivity/org/mozilla/vrbrowser/VRBrowserActivity.java
new file mode 100644
index 000000000..f9d2fe73f
--- /dev/null
+++ b/app/src/common/nativeactivity/org/mozilla/vrbrowser/VRBrowserActivity.java
@@ -0,0 +1,100 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.vrbrowser;
+
+import android.app.NativeActivity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.graphics.SurfaceTexture;
+import android.view.Surface;
+import android.view.SurfaceView;
+
+import org.mozilla.gecko.GeckoSession;
+
+public class VRBrowserActivity extends NativeActivity {
+ static String LOGTAG = "VRBrowser";
+ static final String DEFAULT_URL = "https://mozvr.com";
+ // Used to load the 'native-lib' library on application startup.
+ static {
+ System.loadLibrary("native-lib");
+ }
+
+ private SurfaceView mSurfaceView;
+ private static GeckoSession mSession;
+ private static Surface mBrowserSurface;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.e(LOGTAG,"in onCreate");
+ super.onCreate(savedInstanceState);
+ if (mSession == null) {
+ mSession = new GeckoSession();
+ }
+ getWindow().takeSurface(null);
+ SurfaceView surfaceView = new SurfaceView(this);
+ surfaceView.getHolder().addCallback(this);
+
+ setContentView(surfaceView);
+ loadFromIntent(getIntent());
+ }
+
+ @Override
+ protected void onNewIntent(final Intent intent) {
+ Log.e(LOGTAG,"In onNewIntent");
+ super.onNewIntent(intent);
+ setIntent(intent);
+ final String action = intent.getAction();
+ if (Intent.ACTION_VIEW.equals(action)) {
+ if (intent.getData() != null) {
+ loadFromIntent(intent);
+ }
+ }
+ }
+
+ private void loadFromIntent(final Intent intent) {
+ final Uri uri = intent.getData();
+ Log.e(LOGTAG, "Load URI from intent: " + (uri != null ? uri.toString() : DEFAULT_URL));
+ String uriValue = (uri != null ? uri.toString() : DEFAULT_URL);
+ mSession.loadUri(uriValue);
+ }
+
+ @Override
+ protected void onPause() {
+ Log.e(LOGTAG, "In onPause");
+ super.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ Log.e(LOGTAG, "in onResume");
+ super.onResume();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ }
+
+ private void setSurfaceTexture(String aName, final SurfaceTexture aTexture, final int aWidth, final int aHeight) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ createBrowser(aTexture, aWidth, aHeight);
+ }
+ });
+ }
+
+ private void createBrowser(SurfaceTexture aTexture, int aWidth, int aHeight) {
+ if (aTexture != null) {
+ Log.e(LOGTAG,"In createBrowser");
+ aTexture.setDefaultBufferSize(aWidth, aHeight);
+ mBrowserSurface = new Surface(aTexture);
+ mSession.acquireDisplay().surfaceChanged(mBrowserSurface, aWidth, aHeight);
+ mSession.openWindow(this);
+ }
+ }
+}
diff --git a/app/src/googlevr/AndroidManifest.xml b/app/src/googlevr/AndroidManifest.xml
index 78bcde5ae..4d49ae1b3 100644
--- a/app/src/googlevr/AndroidManifest.xml
+++ b/app/src/googlevr/AndroidManifest.xml
@@ -5,6 +5,7 @@
android:screenOrientation="landscape"
android:enableVrMode="@string/gvr_vr_mode_component"
android:resizeableActivity="false">
+
diff --git a/app/src/main/cpp/BrowserEGLContext.cpp b/app/src/main/cpp/BrowserEGLContext.cpp
new file mode 100644
index 000000000..97e2907c8
--- /dev/null
+++ b/app/src/main/cpp/BrowserEGLContext.cpp
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BrowserEGLContext.h"
+#include "vrb/Logger.h"
+#include
+#include
+
+BrowserEGLContext::BrowserEGLContext()
+ : mMajorVersion(0), mMinorVersion(0), mDisplay(0), mConfig(0), mSurface(0), mContext(0),
+ mNativeWindow(nullptr) {
+}
+
+BrowserEGLContextPtr
+BrowserEGLContext::Create() {
+ return std::make_shared();
+}
+
+bool
+BrowserEGLContext::Initialize(ANativeWindow *aNativeWindow) {
+ mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglInitialize(mDisplay, &mMajorVersion, &mMinorVersion) == EGL_FALSE) {
+ VRB_LOG("eglInitialize() failed: %s", ErrorToString(eglGetError()));
+ return false;
+ }
+
+ // Do NOT use eglChooseConfig, because the Android EGL code pushes in multisample
+ // flags in eglChooseConfig if the user has selected the "force 4x MSAA" option in
+ // settings, and that is completely wasted for the time warp renderer.
+ const int MAX_CONFIGS = 1024;
+
+ EGLConfig configs[MAX_CONFIGS];
+ EGLint numConfigs = 0;
+ if (eglGetConfigs(mDisplay, configs, MAX_CONFIGS, &numConfigs) == EGL_FALSE) {
+ VRB_LOG("eglGetConfigs() failed: %s", ErrorToString(eglGetError()));
+ return false;
+ }
+
+ const EGLint configAttribs[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_SAMPLES, 0,
+ EGL_NONE
+ };
+
+ for (int i = 0; i < numConfigs; ++i) {
+ EGLint value = 0;
+
+ eglGetConfigAttrib(mDisplay, configs[i], EGL_RENDERABLE_TYPE, &value);
+
+ // Check EGL Client Version
+ if ((value & EGL_OPENGL_ES3_BIT_KHR) != EGL_OPENGL_ES3_BIT_KHR) {
+ continue;
+ }
+
+ // EGL_WINDOW_BIT is required so it can share textures with the window context.
+ eglGetConfigAttrib(mDisplay, configs[i], EGL_SURFACE_TYPE, &value);
+ if ((value & (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)) != (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)) {
+ continue;
+ }
+
+ int j = 0;
+ for (; configAttribs[j] != EGL_NONE; j += 2) {
+ eglGetConfigAttrib(mDisplay, configs[i], configAttribs[j], &value);
+ if (value != configAttribs[j + 1]) {
+ break;
+ }
+ }
+ if (configAttribs[j] == EGL_NONE) {
+ mConfig = configs[i];
+ break;
+ }
+ }
+
+ if (mConfig == 0) {
+ VRB_LOG("eglChooseConfig() failed: %s", ErrorToString(eglGetError()));
+ return false;
+ }
+
+
+ //Reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID.
+ mNativeWindow = aNativeWindow;
+ EGLint format;
+ eglGetConfigAttrib(mDisplay, mConfig, EGL_NATIVE_VISUAL_ID, &format);
+ ANativeWindow_setBuffersGeometry(aNativeWindow, 0, 0, format);
+
+ EGLint contextAttribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_NONE
+ };
+
+ mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, contextAttribs);
+ if (mContext == EGL_NO_CONTEXT) {
+ VRB_LOG("eglCreateContext() failed: %s", ErrorToString(eglGetError()));
+ return false;
+ }
+
+ mSurface = eglCreateWindowSurface(mDisplay, mConfig, mNativeWindow, nullptr);
+
+ if (mSurface == EGL_NO_SURFACE) {
+ VRB_LOG("eglCreateWindowSurface() failed: %s", ErrorToString(eglGetError()));
+ eglDestroyContext(mDisplay, mContext);
+ mContext = EGL_NO_CONTEXT;
+ return false;
+ }
+
+ if (eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) == EGL_FALSE) {
+ VRB_LOG("eglMakeCurrent() failed: %s", ErrorToString(eglGetError()));
+ eglDestroySurface(mDisplay, mSurface);
+ eglDestroyContext(mDisplay, mContext);
+ mContext = EGL_NO_CONTEXT;
+ return false;
+ }
+
+ return true;
+}
+
+void
+BrowserEGLContext::Destroy() {
+ if (mDisplay) {
+ if (eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_FALSE) {
+ VRB_LOG("eglMakeCurrent() failed: %s", ErrorToString(eglGetError()));
+ }
+ }
+ if (mContext != EGL_NO_CONTEXT) {
+ if (eglDestroyContext(mDisplay, mContext) == EGL_FALSE) {
+ VRB_LOG("eglDestroyContext() failed: %s", ErrorToString(eglGetError()));
+ }
+ mContext = EGL_NO_CONTEXT;
+ }
+ if (mSurface != EGL_NO_SURFACE) {
+ if (eglDestroySurface(mDisplay, mSurface) == EGL_FALSE) {
+ VRB_LOG("eglDestroySurface() failed: %s", ErrorToString(eglGetError()));
+ }
+ mSurface = EGL_NO_SURFACE;
+ }
+ if (mDisplay) {
+ if (eglTerminate(mDisplay) == EGL_FALSE) {
+ VRB_LOG("eglTerminate() failed: %s", ErrorToString(eglGetError()));
+ }
+ mDisplay = 0;
+ }
+}
+
+
+// Handle Android Life Cycle.
+// Android has started the activity or sent it to foreground.
+// Create a new surface and attach it to the recreated ANativeWindow.
+// Restore the EGLContext.
+void
+BrowserEGLContext::SurfaceChanged(ANativeWindow *aWindow) {
+ if (mSurface != EGL_NO_SURFACE) {
+ return;
+ }
+ mNativeWindow = aWindow;
+ mSurface = eglCreateWindowSurface(mDisplay, mConfig, aWindow, nullptr);
+ if (mSurface == EGL_NO_SURFACE) {
+ VRB_LOG("eglCreateWindowSurface() failed: %s", ErrorToString(eglGetError()));
+ }
+}
+
+// Handle Android Life Cycle.
+// Android has stopped the activity or sent it to background.
+// Release the surface attached to the destroyed ANativeWindow.
+// The EGLContext is not destroyed so it can be restored later.
+void
+BrowserEGLContext::SurfaceDestroyed() {
+ if (mSurface != EGL_NO_SURFACE) {
+ if (eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_FALSE) {
+ VRB_LOG("eglMakeCurrent() failed: %s", ErrorToString(eglGetError()));
+ }
+ if (eglDestroySurface(mDisplay, mSurface) == EGL_FALSE) {
+ VRB_LOG("eglDestroySurface() failed: %s", ErrorToString(eglGetError()));
+ }
+ mSurface = EGL_NO_SURFACE;
+ }
+}
+
+bool
+BrowserEGLContext::IsSurfaceReady() const {
+ return mSurface != EGL_NO_SURFACE;
+}
+
+bool
+BrowserEGLContext::MakeCurrent() {
+ if (eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) == EGL_FALSE) {
+ VRB_LOG("eglMakeCurrent() failed: %s", ErrorToString(eglGetError()));
+ return false;
+ }
+ return true;
+}
+
+bool
+BrowserEGLContext::SwapBuffers() {
+ if (eglSwapBuffers(mDisplay, mSurface) == EGL_FALSE) {
+ VRB_LOG("SwapBuffers() failed: %s", ErrorToString(eglGetError()));
+ return false;
+ }
+ return true;
+}
+
+const char *
+BrowserEGLContext::ErrorToString(EGLint error) {
+ switch (error) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ case EGL_CONTEXT_LOST:
+ return "EGL_CONTEXT_LOST";
+ default:
+ return "Unknown Error";
+ }
+}
diff --git a/app/src/main/cpp/BrowserEGLContext.h b/app/src/main/cpp/BrowserEGLContext.h
new file mode 100644
index 000000000..a679e8ea8
--- /dev/null
+++ b/app/src/main/cpp/BrowserEGLContext.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include
+#include
+
+struct ANativeWindow;
+
+class BrowserEGLContext;
+
+typedef std::shared_ptr BrowserEGLContextPtr;
+typedef std::weak_ptr BrowserEGLContextWeakPtr;
+
+class BrowserEGLContext {
+public:
+ static BrowserEGLContextPtr Create();
+ static const char *ErrorToString(EGLint error);
+
+ bool Initialize(ANativeWindow *aWindow);
+ void Destroy();
+ void SurfaceChanged(ANativeWindow *aWindow);
+ void SurfaceDestroyed();
+ bool IsSurfaceReady() const;
+ bool MakeCurrent();
+ bool SwapBuffers();
+ BrowserEGLContext();
+private:
+ EGLint mMajorVersion;
+ EGLint mMinorVersion;
+ EGLDisplay mDisplay;
+ EGLConfig mConfig;
+ EGLSurface mSurface;
+ EGLContext mContext;
+ ANativeWindow *mNativeWindow;
+};
\ No newline at end of file
diff --git a/app/src/main/cpp/BrowserWorld.cpp b/app/src/main/cpp/BrowserWorld.cpp
index 27cd53db1..86222b079 100644
--- a/app/src/main/cpp/BrowserWorld.cpp
+++ b/app/src/main/cpp/BrowserWorld.cpp
@@ -178,6 +178,11 @@ BrowserWorld::Resume() {
m.paused = false;
}
+bool
+BrowserWorld::IsPaused() const {
+ return m.paused;
+}
+
void
BrowserWorld::InitializeJava(JNIEnv* aEnv, jobject& aActivity, jobject& aAssetManager) {
if (m.context) {
diff --git a/app/src/main/cpp/BrowserWorld.h b/app/src/main/cpp/BrowserWorld.h
index e9146fccf..8b171d76e 100644
--- a/app/src/main/cpp/BrowserWorld.h
+++ b/app/src/main/cpp/BrowserWorld.h
@@ -25,6 +25,7 @@ class BrowserWorld {
void RegisterDeviceDelegate(DeviceDelegatePtr aDelegate);
void Pause();
void Resume();
+ bool IsPaused() const;
void InitializeJava(JNIEnv* aEnv, jobject& aActivity, jobject& aAssetManager);
void InitializeGL();
void ShutdownJava();
diff --git a/app/src/main/cpp/native-lib.cpp b/app/src/main/cpp/native-lib.cpp
index 4e1299928..b42b36d33 100644
--- a/app/src/main/cpp/native-lib.cpp
+++ b/app/src/main/cpp/native-lib.cpp
@@ -10,77 +10,129 @@
#include "BrowserWorld.h"
#include "vrb/Logger.h"
#include "vrb/GLError.h"
-
-static BrowserWorldPtr sWorld;
+#include "BrowserEGLContext.h"
+#include
+#include
+#include
#define JNI_METHOD(return_type, method_name) \
JNIEXPORT return_type JNICALL \
Java_org_mozilla_vrbrowser_VRBrowserActivity_##method_name
-extern "C" {
-JNI_METHOD(void, activityPaused)
-(JNIEnv*, jobject) {
- if (sWorld) {
- sWorld->Pause();
+struct AppContext {
+ vrb::RunnableQueuePtr mQueue;
+ BrowserWorldPtr mWorld;
+ BrowserEGLContextPtr mEgl;
+};
+
+void
+CommandCallback(android_app *aApp, int32_t aCmd) {
+ AppContext *ctx = (AppContext *) aApp->userData;
+
+ switch (aCmd) {
+ // A new ANativeWindow is ready for use. Upon receiving this command,
+ // android_app->window will contain the new window surface.
+ case APP_CMD_INIT_WINDOW:
+ VRB_LOG("APP_CMD_INIT_WINDOW %p", aApp->window);
+ if (!ctx->mEgl) {
+ ctx->mEgl = BrowserEGLContext::Create();
+ ctx->mEgl->Initialize(aApp->window);
+ ctx->mEgl->MakeCurrent();
+ VRB_CHECK(glClearColor(0.0, 0.0, 0.0, 1.0));
+ VRB_CHECK(glEnable(GL_DEPTH_TEST));
+ VRB_CHECK(glEnable(GL_CULL_FACE));
+ ctx->mWorld->InitializeGL();
+ } else {
+ ctx->mEgl->SurfaceChanged(aApp->window);
+ ctx->mEgl->MakeCurrent();
+ }
+ break;
+
+ // The existing ANativeWindow needs to be terminated. Upon receiving this command,
+ // android_app->window still contains the existing window;
+ // after calling android_app_exec_cmd it will be set to NULL.
+ case APP_CMD_TERM_WINDOW:
+ VRB_LOG("APP_CMD_TERM_WINDOW");
+ if (ctx->mEgl) {
+ ctx->mEgl->SurfaceDestroyed();
+ }
+ break;
+ // The app's activity has been paused.
+ case APP_CMD_PAUSE:
+ VRB_LOG("APP_CMD_PAUSE");
+ ctx->mWorld->Pause();
+ break;
+
+ // The app's activity has been resumed.
+ case APP_CMD_RESUME:
+ VRB_LOG("APP_CMD_RESUME");
+ ctx->mWorld->Resume();
+ break;
+
+ // the app's activity is being destroyed,
+ // and waiting for the app thread to clean up and exit before proceeding.
+ case APP_CMD_DESTROY:
+ VRB_LOG("APP_CMD_DESTROY");
+ ctx->mWorld->ShutdownJava();
+ break;
+
+ default:
+ break;
}
}
-JNI_METHOD(void, activityResumed)
-(JNIEnv*, jobject) {
- if (sWorld) {
- sWorld->Resume();
- }
-}
-
-JNI_METHOD(void, activityCreated)
-(JNIEnv* aEnv, jobject aActivity, jobject aAssetManager) {
- if (!sWorld) {
- sWorld = BrowserWorld::Create();
- }
- sWorld->InitializeJava(aEnv, aActivity, aAssetManager);
-}
-
-JNI_METHOD(void, activityDestroyed)
-(JNIEnv* env, jobject) {
- if (sWorld) {
- sWorld->ShutdownJava();
- }
-}
+void
+android_main(android_app *aAppState) {
+ pthread_setname_np(pthread_self(), "VRRenderer");
-JNI_METHOD(void, initializeGL)
-(JNIEnv*, jobject) {
- if (!sWorld) {
- sWorld = BrowserWorld::Create();
+ if (!ALooper_forThread()) {
+ ALooper_prepare(0);
}
- sWorld->InitializeGL();
-}
-
-JNI_METHOD(void, updateGL)
-(JNIEnv*, jobject, int width, int height) {
- VRB_CHECK(glViewport(0, 0, width, height));
- VRB_CHECK(glClearColor(0.0, 0.0, 0.0, 1.0));
- VRB_CHECK(glEnable(GL_DEPTH_TEST));
- VRB_CHECK(glEnable(GL_CULL_FACE));
- // VRB_CHECK(glDisable(GL_CULL_FACE));
- sWorld->SetViewport(width, height);
-}
-
-
-
-JNI_METHOD(void, drawGL)
-(JNIEnv*, jobject) {
- VRB_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
- sWorld->Draw();
-}
-
-JNI_METHOD(void, shutdownGL)
-(JNIEnv*, jobject) {
- if (sWorld) {
- sWorld->ShutdownGL();
+ // Attach JNI thread
+ JNIEnv *jniEnv;
+ (*aAppState->activity->vm).AttachCurrentThread(&jniEnv, NULL);
+
+ // Create Browser context
+ auto appContext = std::make_shared();
+ appContext->mQueue = vrb::RunnableQueue::Create(aAppState->activity->vm);
+ appContext->mWorld = BrowserWorld::Create();
+
+ // Set up activity & SurfaceView life cycle callbacks
+ aAppState->userData = appContext.get();
+ aAppState->onAppCmd = CommandCallback;
+
+ // Main render loop
+ while (true) {
+ int events;
+ android_poll_source *pSource;
+
+ // Loop until all events are read
+ // If the activity is paused use a blocking call to read events.
+ while (ALooper_pollAll(appContext->mWorld->IsPaused() ? -1 : 0,
+ NULL,
+ &events,
+ (void **) &pSource) >= 0) {
+ // Process event.
+ if (pSource) {
+ pSource->process(aAppState, pSource);
+ }
+
+ // Check if we are exiting.
+ if (aAppState->destroyRequested != 0) {
+ appContext->mWorld->ShutdownGL();
+ appContext->mEgl->Destroy();
+ aAppState->activity->vm->DetachCurrentThread();
+ exit(0);
+ }
+ }
+
+ appContext->mQueue->ProcessRunnables();
+ if (!appContext->mWorld->IsPaused() && appContext->mEgl && appContext->mEgl->IsSurfaceReady()) {
+ VRB_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
+ appContext->mWorld->Draw();
+ }
}
}
-
-} // extern "C"
\ No newline at end of file
diff --git a/app/src/main/java/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/main/java/org/mozilla/vrbrowser/VRBrowserActivity.java
deleted file mode 100644
index b05447877..000000000
--- a/app/src/main/java/org/mozilla/vrbrowser/VRBrowserActivity.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.vrbrowser;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.util.Log;
-import android.graphics.SurfaceTexture;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import org.mozilla.gecko.GeckoSession;
-
-public class VRBrowserActivity extends Activity {
- static String LOGTAG = "VRBrowser";
- static final String DEFAULT_URL = "https://mozvr.com";
- // Used to load the 'native-lib' library on application startup.
- static {
- System.loadLibrary("native-lib");
- }
-
- private GLSurfaceView mView;
- private static GeckoSession mSession;
- private static Surface mBrowserSurface;
-
- private final Runnable activityCreatedRunnable = new Runnable() {
- @Override
- public void run() {
- activityCreated(getAssets());
- }
- };
-
- private final Runnable activityDestroyedRunnable = new Runnable() {
- @Override
- public void run() {
- activityDestroyed();
- }
- };
-
- private final Runnable activityPausedRunnable = new Runnable() {
- @Override
- public void run() {
- synchronized (this) {
- activityPaused();
- shutdownGL();
- notifyAll();
- }
- }
- };
-
- private final Runnable activityResumedRunnable = new Runnable() {
- @Override
- public void run() {
- activityResumed();
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- Log.e(LOGTAG,"in onCreate");
- super.onCreate(savedInstanceState);
- if (mSession == null) {
- mSession = new GeckoSession();
- }
- mView = new GLSurfaceView(this);
- mView.setEGLContextClientVersion(3);
- mView.setEGLConfigChooser(8, 8, 8, 0, 16, 0);
- //mView.setPreserveEGLContextOnPause(true);
- mView.setRenderer(
- new GLSurfaceView.Renderer() {
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- Log.e(LOGTAG, "In onSurfaceCreated");
- initializeGL();
- }
-
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- Log.e(LOGTAG, "In onSurfaceChanged");
- updateGL(width, height);
- }
-
- @Override
- public void onDrawFrame(GL10 gl) {
- //Log.e(LOGTAG, "in onDrawFrame");
- drawGL();
- }
- });
- mView.queueEvent(activityCreatedRunnable);
- setContentView(mView);
- loadFromIntent(getIntent());
- }
-
- @Override
- protected void onNewIntent(final Intent intent) {
- Log.e(LOGTAG,"In onNewIntent");
- super.onNewIntent(intent);
- setIntent(intent);
- final String action = intent.getAction();
- if (Intent.ACTION_VIEW.equals(action)) {
- if (intent.getData() != null) {
- loadFromIntent(intent);
- }
- }
- }
-
- private void loadFromIntent(final Intent intent) {
- final Uri uri = intent.getData();
- Log.e(LOGTAG, "Load URI from intent: " + (uri != null ? uri.toString() : DEFAULT_URL));
- String uriValue = (uri != null ? uri.toString() : DEFAULT_URL);
- mSession.loadUri(uriValue);
- }
-
- @Override
- protected void onPause() {
- Log.e(LOGTAG, "In onPause");
- synchronized (activityPausedRunnable) {
- mView.queueEvent(activityPausedRunnable);
- try {
- activityPausedRunnable.wait();
- } catch(InterruptedException e) {
-
- }
- }
- mView.onPause();
- super.onPause();
- }
-
- @Override
- protected void onResume() {
- Log.e(LOGTAG, "in onResume");
- super.onResume();
- mView.onResume();
- mView.queueEvent(activityResumedRunnable);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mView.queueEvent(activityDestroyedRunnable);
- }
-
- private void setSurfaceTexture(String aName, final SurfaceTexture aTexture, final int aWidth, final int aHeight) {
- runOnUiThread(new Runnable() {
- public void run() {
- createBrowser(aTexture, aWidth, aHeight);
- }
- });
- }
-
- private void createBrowser(SurfaceTexture aTexture, int aWidth, int aHeight) {
- if (aTexture != null) {
- Log.e(LOGTAG,"In createBrowser");
- aTexture.setDefaultBufferSize(aWidth, aHeight);
- mBrowserSurface = new Surface(aTexture);
- mSession.acquireDisplay().surfaceChanged(mBrowserSurface, aWidth, aHeight);
- mSession.openWindow(this);
- }
- }
-
- private native void activityCreated(Object aAssetManager);
- private native void activityPaused();
- private native void activityResumed();
- private native void activityDestroyed();
- private native void initializeGL();
- private native void updateGL(int width, int height);
- private native void shutdownGL();
- private native void drawGL();
-}
diff --git a/app/src/oculusvr/AndroidManifest.xml b/app/src/oculusvr/AndroidManifest.xml
index 690489ab0..4aa2006b8 100644
--- a/app/src/oculusvr/AndroidManifest.xml
+++ b/app/src/oculusvr/AndroidManifest.xml
@@ -3,6 +3,7 @@
+
diff --git a/app/src/svr/AndroidManifest.xml b/app/src/svr/AndroidManifest.xml
index 585144010..4ca879e12 100644
--- a/app/src/svr/AndroidManifest.xml
+++ b/app/src/svr/AndroidManifest.xml
@@ -8,6 +8,7 @@
+