Bug 1413362 - part 1: Add GeckoVRManager to support GVR WebVR implementation on Android r=jchen,snorp draft
authorRandall Barker <rbarker@mozilla.com>
Tue, 31 Oct 2017 16:40:41 -0700
changeset 693024 8faeae89d6d126f435d94fc6f99a5c0458d2f7c8
parent 693013 7ee2f9d5bdcc7fa122f21c05244426eaa50d0b56
child 693025 11ffa2271383d63b367ebf734fc3117d8535999d
push id87675
push userbmo:rbarker@mozilla.com
push dateFri, 03 Nov 2017 21:24:57 +0000
reviewersjchen, snorp
bugs1413362
milestone58.0a1
Bug 1413362 - part 1: Add GeckoVRManager to support GVR WebVR implementation on Android r=jchen,snorp MozReview-Commit-ID: C7XTF8N1W9a
mobile/android/base/moz.build
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
widget/android/GeckoVRManager.h
widget/android/GeneratedJNINatives.h
widget/android/GeneratedJNIWrappers.cpp
widget/android/GeneratedJNIWrappers.h
widget/android/moz.build
widget/android/nsAppShell.cpp
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -384,16 +384,17 @@ gvjar.sources += [geckoview_source_dir +
     'GeckoProfile.java',
     'GeckoProfileDirectories.java',
     'GeckoScreenOrientation.java',
     'GeckoSharedPrefs.java',
     'GeckoThread.java',
     'GeckoView.java',
     'GeckoViewHandler.java',
     'GeckoViewSettings.java',
+    'GeckoVRManager.java',
     'gfx/BitmapUtils.java',
     'gfx/BufferedImage.java',
     'gfx/BufferedImageGLInfo.java',
     'gfx/DynamicToolbarAnimator.java',
     'gfx/FloatSize.java',
     'gfx/FullScreenState.java',
     'gfx/GeckoLayerClient.java',
     'gfx/GeckoSurface.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
@@ -0,0 +1,125 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
+ * 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.gecko;
+
+import org.mozilla.gecko.annotation.WrapForJNI;
+import org.mozilla.gecko.util.ThreadUtils;
+
+public class GeckoVRManager {
+    /**
+     * GeckoView applications implement this interface to provide GVR support for WebVR.
+     */
+    public interface GVRDelegate {
+        /**
+         * Creates non-presenting context. Will be invoked in the compositor thread.
+         */
+        long createNonPresentingContext();
+        /**
+         * Destroys non-presenting context. Will be invoked in the compositor thread.
+         */
+        void destroyNonPresentingContext();
+        /**
+         * Called when WebVR needs a presenting context. Will be invoked in the UI thread.
+         */
+        boolean enableVRMode();
+        /**
+         * Called when WebVR has finished presenting. Will be invoked in the UI thread.
+         */
+        void disableVRMode();
+    }
+
+    private static GVRDelegate mGVRDelegate;
+
+    /**
+     * Set the GVR Delegate for GeckoView.
+     * @param delegate GVRDelegate instance or null to unset.
+     */
+    public static void setGVRDelegate(GVRDelegate delegate) {
+        mGVRDelegate = delegate;
+    }
+
+    /**
+     * Set the GVR paused state.
+     * @param aPaused True if the application is being paused, False if the
+     * application is resuming.
+     */
+    @WrapForJNI(calledFrom = "ui")
+    public static native void setGVRPaused(final boolean aPaused);
+
+    /**
+     * Set the GVR presenting context.
+     * @param aContext GVR context to use when WebVR starts to present. Pass in
+     * zero to stop presenting.
+     */
+    @WrapForJNI(calledFrom = "ui")
+    public static native void setGVRPresentingContext(final long aContext);
+
+    /**
+     * Inform WebVR that the non-presenting context needs to be destroyed.
+     */
+    @WrapForJNI(calledFrom = "ui")
+    public static native void cleanupGVRNonPresentingContext();
+
+    @WrapForJNI
+    /* package */ static boolean isGVRPresent() {
+        return mGVRDelegate != null;
+    }
+
+    @WrapForJNI
+    /* package */ static long createGVRNonPresentingContext() {
+        if (mGVRDelegate == null) {
+            return 0;
+        }
+        return mGVRDelegate.createNonPresentingContext();
+    }
+
+    @WrapForJNI
+    /* package */ static void destroyGVRNonPresentingContext() {
+        if (mGVRDelegate == null) {
+            return;
+        }
+        mGVRDelegate.destroyNonPresentingContext();
+    }
+
+    @WrapForJNI
+    /* package */ static void enableVRMode() {
+        if (!ThreadUtils.isOnUiThread()) {
+            ThreadUtils.postToUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    enableVRMode();
+                }
+            });
+            return;
+        }
+
+        if (mGVRDelegate == null) {
+            return;
+        }
+
+        mGVRDelegate.enableVRMode();
+    }
+
+    @WrapForJNI
+    /* package */ static void disableVRMode() {
+        if (!ThreadUtils.isOnUiThread()) {
+            ThreadUtils.postToUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    disableVRMode();
+                }
+            });
+            return;
+        }
+
+        if (mGVRDelegate == null) {
+            return;
+        }
+
+        mGVRDelegate.disableVRMode();
+    }
+}
new file mode 100644
--- /dev/null
+++ b/widget/android/GeckoVRManager.h
@@ -0,0 +1,82 @@
+/* -*- 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/. */
+
+#ifndef mozilla_GeckoVRManager_h_
+#define mozilla_GeckoVRManager_h_
+
+#include "GeneratedJNINatives.h"
+#include "mozilla/jni/Utils.h"
+
+#if defined(MOZ_ANDROID_GOOGLE_VR)
+#include "gfxVRGVRAPI.h"
+extern bool SetupGVRJNI(JNIEnv* env);
+#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+
+namespace mozilla {
+
+class GeckoVRManager
+    : public mozilla::java::GeckoVRManager::Natives<mozilla::GeckoVRManager>
+{
+  typedef mozilla::java::GeckoVRManager::Natives<mozilla::GeckoVRManager> Super;
+public:
+  static void Init()
+  {
+    Super::Init();
+#if defined(MOZ_ANDROID_GOOGLE_VR)
+    SetupGVRJNI(jni::GetGeckoThreadEnv());
+#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+  }
+
+  static void SetGVRPresentingContext(const int64_t aContext)
+  {
+#if defined(MOZ_ANDROID_GOOGLE_VR)
+    mozilla::gfx::SetGVRPresentingContext((void*)aContext);
+#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+  }
+
+  static void CleanupGVRNonPresentingContext()
+  {
+#if defined(MOZ_ANDROID_GOOGLE_VR)
+    mozilla::gfx::CleanupGVRNonPresentingContext();
+#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+  }
+
+  static void SetGVRPaused(const bool aPaused)
+  {
+#if defined(MOZ_ANDROID_GOOGLE_VR)
+    mozilla::gfx::SetGVRPaused(aPaused);
+#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+  }
+
+  static void* CreateGVRNonPresentingContext()
+  {
+    return (void*)mozilla::java::GeckoVRManager::CreateGVRNonPresentingContext();
+  }
+
+  static void DestroyGVRNonPresentingContext()
+  {
+    mozilla::java::GeckoVRManager::DestroyGVRNonPresentingContext();
+  }
+
+  static void EnableVRMode()
+  {
+    mozilla::java::GeckoVRManager::EnableVRMode();
+  }
+
+  static void DisableVRMode()
+  {
+    mozilla::java::GeckoVRManager::DisableVRMode();
+  }
+
+  static bool IsGVRPresent()
+  {
+    return mozilla::java::GeckoVRManager::IsGVRPresent();
+  }
+
+};
+
+} // namespace mozilla
+
+#endif // mozilla_GeckoVRManager_h_
--- a/widget/android/GeneratedJNINatives.h
+++ b/widget/android/GeneratedJNINatives.h
@@ -253,16 +253,39 @@ const JNINativeMethod GeckoThread::Nativ
             ::template Wrap<&Impl::SpeculativeConnect>),
 
     mozilla::jni::MakeNativeMethod<GeckoThread::WaitOnGecko_t>(
             mozilla::jni::NativeStub<GeckoThread::WaitOnGecko_t, Impl>
             ::template Wrap<&Impl::WaitOnGecko>)
 };
 
 template<class Impl>
+class GeckoVRManager::Natives : public mozilla::jni::NativeImpl<GeckoVRManager, Impl>
+{
+public:
+    static const JNINativeMethod methods[3];
+};
+
+template<class Impl>
+const JNINativeMethod GeckoVRManager::Natives<Impl>::methods[] = {
+
+    mozilla::jni::MakeNativeMethod<GeckoVRManager::CleanupGVRNonPresentingContext_t>(
+            mozilla::jni::NativeStub<GeckoVRManager::CleanupGVRNonPresentingContext_t, Impl>
+            ::template Wrap<&Impl::CleanupGVRNonPresentingContext>),
+
+    mozilla::jni::MakeNativeMethod<GeckoVRManager::SetGVRPaused_t>(
+            mozilla::jni::NativeStub<GeckoVRManager::SetGVRPaused_t, Impl>
+            ::template Wrap<&Impl::SetGVRPaused>),
+
+    mozilla::jni::MakeNativeMethod<GeckoVRManager::SetGVRPresentingContext_t>(
+            mozilla::jni::NativeStub<GeckoVRManager::SetGVRPresentingContext_t, Impl>
+            ::template Wrap<&Impl::SetGVRPresentingContext>)
+};
+
+template<class Impl>
 class GeckoView::Window::Natives : public mozilla::jni::NativeImpl<Window, Impl>
 {
 public:
     static const JNINativeMethod methods[4];
 };
 
 template<class Impl>
 const JNINativeMethod GeckoView::Window::Natives<Impl>::methods[] = {
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -945,16 +945,68 @@ auto GeckoThread::State::RESTARTING() ->
 constexpr char GeckoThread::State::RUNNING_t::name[];
 constexpr char GeckoThread::State::RUNNING_t::signature[];
 
 auto GeckoThread::State::RUNNING() -> State::LocalRef
 {
     return mozilla::jni::Field<RUNNING_t>::Get(State::Context(), nullptr);
 }
 
+const char GeckoVRManager::name[] =
+        "org/mozilla/gecko/GeckoVRManager";
+
+constexpr char GeckoVRManager::CleanupGVRNonPresentingContext_t::name[];
+constexpr char GeckoVRManager::CleanupGVRNonPresentingContext_t::signature[];
+
+constexpr char GeckoVRManager::CreateGVRNonPresentingContext_t::name[];
+constexpr char GeckoVRManager::CreateGVRNonPresentingContext_t::signature[];
+
+auto GeckoVRManager::CreateGVRNonPresentingContext() -> int64_t
+{
+    return mozilla::jni::Method<CreateGVRNonPresentingContext_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::DestroyGVRNonPresentingContext_t::name[];
+constexpr char GeckoVRManager::DestroyGVRNonPresentingContext_t::signature[];
+
+auto GeckoVRManager::DestroyGVRNonPresentingContext() -> void
+{
+    return mozilla::jni::Method<DestroyGVRNonPresentingContext_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::DisableVRMode_t::name[];
+constexpr char GeckoVRManager::DisableVRMode_t::signature[];
+
+auto GeckoVRManager::DisableVRMode() -> void
+{
+    return mozilla::jni::Method<DisableVRMode_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::EnableVRMode_t::name[];
+constexpr char GeckoVRManager::EnableVRMode_t::signature[];
+
+auto GeckoVRManager::EnableVRMode() -> void
+{
+    return mozilla::jni::Method<EnableVRMode_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::IsGVRPresent_t::name[];
+constexpr char GeckoVRManager::IsGVRPresent_t::signature[];
+
+auto GeckoVRManager::IsGVRPresent() -> bool
+{
+    return mozilla::jni::Method<IsGVRPresent_t>::Call(GeckoVRManager::Context(), nullptr);
+}
+
+constexpr char GeckoVRManager::SetGVRPaused_t::name[];
+constexpr char GeckoVRManager::SetGVRPaused_t::signature[];
+
+constexpr char GeckoVRManager::SetGVRPresentingContext_t::name[];
+constexpr char GeckoVRManager::SetGVRPresentingContext_t::signature[];
+
 const char GeckoView::name[] =
         "org/mozilla/gecko/GeckoView";
 
 const char GeckoView::State::name[] =
         "org/mozilla/gecko/GeckoView$State";
 
 constexpr char GeckoView::State::INITIAL_t::name[];
 constexpr char GeckoView::State::INITIAL_t::signature[];
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -2823,16 +2823,177 @@ public:
 
     static auto RUNNING() -> State::LocalRef;
 
     static const mozilla::jni::CallingThread callingThread =
             mozilla::jni::CallingThread::ANY;
 
 };
 
+class GeckoVRManager : public mozilla::jni::ObjectBase<GeckoVRManager>
+{
+public:
+    static const char name[];
+
+    explicit GeckoVRManager(const Context& ctx) : ObjectBase<GeckoVRManager>(ctx) {}
+
+    struct CleanupGVRNonPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "cleanupGVRNonPresentingContext";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::UI;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    struct CreateGVRNonPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef int64_t ReturnType;
+        typedef int64_t SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "createGVRNonPresentingContext";
+        static constexpr char signature[] =
+                "()J";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto CreateGVRNonPresentingContext() -> int64_t;
+
+    struct DestroyGVRNonPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "destroyGVRNonPresentingContext";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto DestroyGVRNonPresentingContext() -> void;
+
+    struct DisableVRMode_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "disableVRMode";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto DisableVRMode() -> void;
+
+    struct EnableVRMode_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "enableVRMode";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto EnableVRMode() -> void;
+
+    struct IsGVRPresent_t {
+        typedef GeckoVRManager Owner;
+        typedef bool ReturnType;
+        typedef bool SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "isGVRPresent";
+        static constexpr char signature[] =
+                "()Z";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static auto IsGVRPresent() -> bool;
+
+    struct SetGVRPaused_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<
+                bool> Args;
+        static constexpr char name[] = "setGVRPaused";
+        static constexpr char signature[] =
+                "(Z)V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::UI;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    struct SetGVRPresentingContext_t {
+        typedef GeckoVRManager Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<
+                int64_t> Args;
+        static constexpr char name[] = "setGVRPresentingContext";
+        static constexpr char signature[] =
+                "(J)V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::UI;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static const mozilla::jni::CallingThread callingThread =
+            mozilla::jni::CallingThread::ANY;
+
+    template<class Impl> class Natives;
+};
+
 class GeckoView : public mozilla::jni::ObjectBase<GeckoView>
 {
 public:
     static const char name[];
 
     explicit GeckoView(const Context& ctx) : ObjectBase<GeckoView>(ctx) {}
 
     class State;
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -61,16 +61,17 @@ include('/ipc/chromium/chromium-config.m
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/system/android',
     '/gfx/2d',
+    '/gfx/vr',
     '/layout/painting',
     '/netwerk/base',
     '/netwerk/cache',
     '/widget',
     '/xpcom/threads',
 ]
 
 CXXFLAGS += ['-Wno-error=shadow']
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -64,16 +64,17 @@
 
 #include "AndroidAlerts.h"
 #include "AndroidUiThread.h"
 #include "ANRReporter.h"
 #include "GeckoBatteryManager.h"
 #include "GeckoNetworkManager.h"
 #include "GeckoProcessManager.h"
 #include "GeckoScreenOrientation.h"
+#include "GeckoVRManager.h"
 #include "PrefsHelper.h"
 #include "fennec/MemoryMonitor.h"
 #include "fennec/Telemetry.h"
 #include "fennec/ThumbnailHelper.h"
 
 #ifdef DEBUG_ANDROID_EVENTS
 #define EVLOG(args...)  ALOG(args)
 #else
@@ -402,16 +403,17 @@ nsAppShell::nsAppShell()
         AndroidBridge::ConstructBridge();
         GeckoAppShellSupport::Init();
         GeckoThreadSupport::Init();
         mozilla::GeckoBatteryManager::Init();
         mozilla::GeckoNetworkManager::Init();
         mozilla::GeckoProcessManager::Init();
         mozilla::GeckoScreenOrientation::Init();
         mozilla::PrefsHelper::Init();
+        mozilla::GeckoVRManager::Init();
         nsWindow::InitNatives();
 
         if (jni::IsFennec()) {
             mozilla::ANRReporter::Init();
             mozilla::MemoryMonitor::Init();
             mozilla::widget::Telemetry::Init();
             mozilla::ThumbnailHelper::Init();
         }