Bug 1465816 - Add initial code needed to support gfxVRExternal on android r=kip,jchen draft
authorRandall Barker <rbarker@mozilla.com>
Mon, 04 Jun 2018 15:45:04 -0700
changeset 803893 93ba1d1fac50d8d9bb1b71f87c0e35fbaf2ba063
parent 803892 3076a2ea0082c0831817859fb8ee10123fa594ab
push id112225
push userbmo:rbarker@mozilla.com
push dateMon, 04 Jun 2018 23:42:11 +0000
reviewerskip, jchen
bugs1465816
milestone62.0a1
Bug 1465816 - Add initial code needed to support gfxVRExternal on android r=kip,jchen MozReview-Commit-ID: 9rXXqIvyvhp
gfx/vr/VRDisplayClient.cpp
gfx/vr/VRDisplayHost.cpp
gfx/vr/VRDisplayHost.h
gfx/vr/VRManager.cpp
gfx/vr/external_api/moz_external_vr.h
gfx/vr/gfxVR.h
gfx/vr/gfxVRExternal.cpp
gfx/vr/gfxVRExternal.h
gfx/vr/gfxVROSVR.cpp
gfx/vr/gfxVROSVR.h
gfx/vr/gfxVRPuppet.cpp
gfx/vr/gfxVRPuppet.h
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRMessageUtils.h
gfx/vr/moz.build
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
widget/android/GeckoVRManager.h
widget/android/nsAppShell.cpp
--- a/gfx/vr/VRDisplayClient.cpp
+++ b/gfx/vr/VRDisplayClient.cpp
@@ -76,27 +76,27 @@ VRDisplayClient::SetGroupMask(uint32_t a
 {
   VRManagerChild *vm = VRManagerChild::Get();
   vm->SendSetGroupMask(mDisplayInfo.mDisplayID, aGroupMask);
 }
 
 bool
 VRDisplayClient::IsPresentationGenerationCurrent() const
 {
-  if (mLastPresentingGeneration != mDisplayInfo.mPresentingGeneration) {
+  if (mLastPresentingGeneration != mDisplayInfo.mDisplayState.mPresentingGeneration) {
     return false;
   }
 
   return true;
 }
 
 void
 VRDisplayClient::MakePresentationGenerationCurrent()
 {
-  mLastPresentingGeneration = mDisplayInfo.mPresentingGeneration;
+  mLastPresentingGeneration = mDisplayInfo.mDisplayState.mPresentingGeneration;
 }
 
 void
 VRDisplayClient::FireEvents()
 {
   VRManagerChild *vm = VRManagerChild::Get();
   // Only fire these events for non-chrome VR sessions
   bool isPresenting = (mDisplayInfo.mPresentingGroups & kVRGroupContent) != 0;
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -21,19 +21,19 @@
 #include "mozilla/layers/TextureD3D11.h"
 
 #elif defined(XP_MACOSX)
 
 #include "mozilla/gfx/MacIOSurface.h"
 
 #endif
 
-#if defined(MOZ_ANDROID_GOOGLE_VR)
+#if defined(MOZ_WIDGET_ANDROID)
 #include "mozilla/layers/CompositorThread.h"
-#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+#endif // defined(MOZ_WIDGET_ANDROID)
 
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 VRDisplayHost::AutoRestoreRenderState::AutoRestoreRenderState(VRDisplayHost* aDisplay)
   : mDisplay(aDisplay)
@@ -72,17 +72,17 @@ VRDisplayHost::VRDisplayHost(VRDeviceTyp
  , mFrameStarted(false)
 {
   MOZ_COUNT_CTOR(VRDisplayHost);
   mDisplayInfo.mType = aType;
   mDisplayInfo.mDisplayID = VRSystemManager::AllocateDisplayID();
   mDisplayInfo.mPresentingGroups = 0;
   mDisplayInfo.mGroupMask = kVRGroupContent;
   mDisplayInfo.mFrameId = 0;
-  mDisplayInfo.mPresentingGeneration = 0;
+  mDisplayInfo.mDisplayState.mPresentingGeneration = 0;
   mDisplayInfo.mDisplayState.mDisplayName[0] = '\0';
 }
 
 VRDisplayHost::~VRDisplayHost()
 {
   if (mSubmitThread) {
     mSubmitThread->Shutdown();
     mSubmitThread = nullptr;
@@ -263,19 +263,19 @@ VRDisplayHost::NotifyVSync()
 }
 
 void
 VRDisplayHost::SubmitFrameInternal(const layers::SurfaceDescriptor &aTexture,
                                    uint64_t aFrameId,
                                    const gfx::Rect& aLeftEyeRect,
                                    const gfx::Rect& aRightEyeRect)
 {
-#if !defined(MOZ_ANDROID_GOOGLE_VR)
+#if !defined(MOZ_WIDGET_ANDROID)
   MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
-#endif // !defined(MOZ_ANDROID_GOOGLE_VR)
+#endif // !defined(MOZ_WIDGET_ANDROID)
   AUTO_PROFILER_TRACING("VR", "SubmitFrameAtVRDisplayHost");
 
   mFrameStarted = false;
   switch (aTexture.type()) {
 
 #if defined(XP_WIN)
     case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
       if (!CreateD3DObjects()) {
@@ -332,32 +332,32 @@ VRDisplayHost::SubmitFrameInternal(const
       }
       IntSize texSize = gfx::IntSize(surf->GetDevicePixelWidth(),
                                      surf->GetDevicePixelHeight());
       if (!SubmitFrame(surf, texSize, aLeftEyeRect, aRightEyeRect)) {
         return;
       }
       break;
     }
-#elif defined(MOZ_ANDROID_GOOGLE_VR)
-    case SurfaceDescriptor::TEGLImageDescriptor: {
-      const EGLImageDescriptor& desc = aTexture.get_EGLImageDescriptor();
-      if (!SubmitFrame(&desc, aLeftEyeRect, aRightEyeRect)) {
+#elif defined(MOZ_WIDGET_ANDROID)
+    case SurfaceDescriptor::TSurfaceTextureDescriptor: {
+      const SurfaceTextureDescriptor& desc = aTexture.get_SurfaceTextureDescriptor();
+      if (!SubmitFrame(desc, aLeftEyeRect, aRightEyeRect)) {
         return;
       }
       break;
     }
 #endif
     default: {
       NS_WARNING("Unsupported SurfaceDescriptor type for VR layer texture");
       return;
     }
   }
 
-#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_ANDROID_GOOGLE_VR)
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
 
   /**
    * Trigger the next VSync immediately after we are successfully
    * submitting frames.  As SubmitFrame is responsible for throttling
    * the render loop, if we don't successfully call it, we shouldn't trigger
    * NotifyVRVsync immediately, as it will run unbounded.
    * If NotifyVRVsync is not called here due to SubmitFrame failing, the
    * fallback "watchdog" code in VRDisplayHost::NotifyVSync() will cause
@@ -376,43 +376,43 @@ VRDisplayHost::SubmitFrameInternal(const
 
 void
 VRDisplayHost::SubmitFrame(VRLayerParent* aLayer,
                            const layers::SurfaceDescriptor &aTexture,
                            uint64_t aFrameId,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect)
 {
-#if !defined(MOZ_ANDROID_GOOGLE_VR)
+#if !defined(MOZ_WIDGET_ANDROID)
   if (!mSubmitThread) {
     mSubmitThread = new VRThread(NS_LITERAL_CSTRING("VR_SubmitFrame"));
   }
-#endif // !defined(MOZ_ANDROID_GOOGLE_VR)
+#endif // !defined(MOZ_WIDGET_ANDROID)
 
   if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
     // Suppress layers hidden by the group mask
     return;
   }
 
   // Ensure that we only accept the first SubmitFrame call per RAF cycle.
   if (!mFrameStarted || aFrameId != mDisplayInfo.mFrameId) {
     return;
   }
 
   RefPtr<Runnable> submit =
     NewRunnableMethod<StoreCopyPassByConstLRef<layers::SurfaceDescriptor>, uint64_t,
       StoreCopyPassByConstLRef<gfx::Rect>, StoreCopyPassByConstLRef<gfx::Rect>>(
       "gfx::VRDisplayHost::SubmitFrameInternal", this, &VRDisplayHost::SubmitFrameInternal,
       aTexture, aFrameId, aLeftEyeRect, aRightEyeRect);
-#if !defined(MOZ_ANDROID_GOOGLE_VR)
+#if !defined(MOZ_WIDGET_ANDROID)
   mSubmitThread->Start();
   mSubmitThread->PostTask(submit.forget());
 #else
   CompositorThreadHolder::Loop()->PostTask(submit.forget());
-#endif // defined(MOZ_ANDROID_GOOGLE_VR)
+#endif // defined(MOZ_WIDGET_ANDROID)
 }
 
 bool
 VRDisplayHost::CheckClearDisplayInfoDirty()
 {
   if (mDisplayInfo == mLastUpdateDisplayInfo) {
     return false;
   }
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -81,18 +81,18 @@ protected:
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) = 0;
 #elif defined(XP_MACOSX)
   virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) = 0;
-#elif defined(MOZ_ANDROID_GOOGLE_VR)
-  virtual bool SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor,
+#elif defined(MOZ_WIDGET_ANDROID)
+  virtual bool SubmitFrame(const mozilla::layers::SurfaceTextureDescriptor& aSurface,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) = 0;
 #endif
 
   VRDisplayInfo mDisplayInfo;
 
   nsTArray<VRLayerParent *> mLayers;
   // Weak reference to mLayers entries are cleared in
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -21,19 +21,16 @@
 #include "gfxVRExternal.h"
 #if defined(XP_WIN)
 #include "gfxVROculus.h"
 #endif
 #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
 #include "gfxVROpenVR.h"
 #include "gfxVROSVR.h"
 #endif
-#if defined(MOZ_ANDROID_GOOGLE_VR)
-#include "gfxVRGVR.h"
-#endif // MOZ_ANDROID_GOOGLE_VR
 
 #include "gfxVRPuppet.h"
 #include "ipc/VRLayerParent.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::gl;
@@ -99,23 +96,16 @@ VRManager::VRManager()
 
   // OSVR is cross platform compatible
   mgr = VRSystemManagerOSVR::Create();
   if (mgr) {
       mManagers.AppendElement(mgr);
   }
 #endif
 
-#if defined(MOZ_ANDROID_GOOGLE_VR)
-   mgr = VRSystemManagerGVR::Create();
-   if (mgr) {
-     mManagers.AppendElement(mgr);
-   }
-#endif // defined(MOZ_ANDROID_GOOGLE_VR)
-
   // Enable gamepad extensions while VR is enabled.
   // Preference only can be set at the Parent process.
   if (XRE_IsParentProcess() && gfxPrefs::VREnabled()) {
     Preferences::SetBool("dom.gamepad.extensions.enabled", true);
   }
 }
 
 VRManager::~VRManager()
--- a/gfx/vr/external_api/moz_external_vr.h
+++ b/gfx/vr/external_api/moz_external_vr.h
@@ -11,24 +11,30 @@
 #include <stdint.h>
 #include <type_traits>
 
 #ifdef MOZILLA_INTERNAL_API
 #include "mozilla/TypedEnumBits.h"
 #include "mozilla/gfx/2D.h"
 #endif // MOZILLA_INTERNAL_API
 
+#if defined(__ANDROID__)
+#include <pthread.h>
+#endif // defined(__ANDROID__)
+
 namespace mozilla {
 #ifdef MOZILLA_INTERNAL_API
 namespace dom {
   enum class GamepadHand : uint8_t;
 }
 #endif //  MOZILLA_INTERNAL_API
 namespace gfx {
 
+static const int32_t kVRExternalVersion = 0;
+
 // We assign VR presentations to groups with a bitmask.
 // Currently, we will only display either content or chrome.
 // Later, we will have more groups to support VR home spaces and
 // multitasking environments.
 // These values are not exposed to regular content and only affect
 // chrome-only API's.  They may be changed at any time.
 static const uint32_t kVRGroupNone = 0;
 static const uint32_t kVRGroupContent = 1 << 0;
@@ -211,26 +217,30 @@ struct VRFieldOfView {
 struct VRDisplayState
 {
   enum Eye {
     Eye_Left,
     Eye_Right,
     NumEyes
   };
 
+#if defined(__ANDROID__)
+  bool shutdown;
+#endif // defined(__ANDROID__)
   char mDisplayName[kVRDisplayNameMaxLen];
   VRDisplayCapabilityFlags mCapabilityFlags;
   VRFieldOfView mEyeFOV[VRDisplayState::NumEyes];
   Point3D_POD mEyeTranslation[VRDisplayState::NumEyes];
   IntSize_POD mEyeResolution;
   bool mIsConnected;
   bool mIsMounted;
   FloatSize_POD mStageSize;
   // We can't use a Matrix4x4 here unless we ensure it's a POD type
   float mSittingToStandingTransform[16];
+  uint32_t mPresentingGeneration;
 };
 
 struct VRControllerState
 {
   char mControllerName[kVRControllerNameMaxLen];
 #ifdef MOZILLA_INTERNAL_API
   dom::GamepadHand mHand;
 #else
@@ -291,34 +301,49 @@ struct VRLayerState
   union {
     VRLayer_2D_Content layer_2d_content;
     VRLayer_Stereo_Immersive layer_stereo_immersive;
   };
 };
 
 struct VRBrowserState
 {
+#if defined(__ANDROID__)
+  bool shutdown;
+#endif // defined(__ANDROID__)
   VRLayerState layerState[kVRLayerMaxCount];
 };
 
 struct VRSystemState
 {
+  uint32_t presentingGeneration;
   VRDisplayState displayState;
   VRHMDSensorState sensorState;
   VRControllerState controllerState[kVRControllerMaxCount];
 };
 
 struct VRExternalShmem
 {
+  int32_t version;
+  int32_t size;
+#if defined(__ANDROID__)
+  pthread_mutex_t systemMutex;
+  pthread_mutex_t browserMutex;
+#else
   int64_t generationA;
+#endif // defined(__ANDROID__)
   VRSystemState state;
+#if !defined(__ANDROID__)
   int64_t generationB;
   int64_t browserGenerationA;
+#endif // !defined(__ANDROID__)
   VRBrowserState browserState;
+#if !defined(__ANDROID__)
   int64_t browserGenerationB;
+#endif // !defined(__ANDROID__)
 };
 
 // As we are memcpy'ing VRExternalShmem and its members around, it must be a POD type
 static_assert(std::is_pod<VRExternalShmem>::value, "VRExternalShmem must be a POD type.");
 
 } // namespace gfx
 } // namespace mozilla
 
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -54,17 +54,16 @@ enum class VRDeviceType : uint16_t {
 
 struct VRDisplayInfo
 {
   uint32_t mDisplayID;
   VRDeviceType mType;
   uint32_t mPresentingGroups;
   uint32_t mGroupMask;
   uint64_t mFrameId;
-  uint32_t mPresentingGeneration;
   VRDisplayState mDisplayState;
 
   VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames];
   const VRHMDSensorState& GetSensorState() const
   {
     return mLastSensorState[mFrameId % kVRMaxLatencyFrames];
   }
 
@@ -91,18 +90,17 @@ struct VRDisplayInfo
       }
     }
     // Note that mDisplayState is asserted to be a POD type, so memcmp is safe
     return mType == other.mType &&
            mDisplayID == other.mDisplayID &&
            memcmp(&mDisplayState, &other.mDisplayState, sizeof(VRDisplayState)) == 0 &&
            mPresentingGroups == other.mPresentingGroups &&
            mGroupMask == other.mGroupMask &&
-           mFrameId == other.mFrameId &&
-           mPresentingGeneration == other.mPresentingGeneration;
+           mFrameId == other.mFrameId;
   }
 
   bool operator!=(const VRDisplayInfo& other) const {
     return !(*this == other);
   }
 };
 
 struct VRSubmitFrameResultInfo
--- a/gfx/vr/gfxVRExternal.cpp
+++ b/gfx/vr/gfxVRExternal.cpp
@@ -19,17 +19,21 @@
 static const char* kShmemName = "moz.gecko.vr_ext.0.0.1";
 #elif defined(XP_MACOSX)
 #include "mozilla/gfx/MacIOSurface.h"
 #include <sys/mman.h>
 #include <sys/stat.h>        /* For mode constants */
 #include <fcntl.h>           /* For O_* constants */
 #include <errno.h>
 static const char* kShmemName = "/moz.gecko.vr_ext.0.0.1";
-#endif
+#elif defined(MOZ_WIDGET_ANDROID)
+#include <string.h>
+#include <pthread.h>
+#include "GeckoVRManager.h"
+#endif // defined(MOZ_WIDGET_ANDROID)
 
 #include "gfxVRExternal.h"
 #include "VRManagerParent.h"
 #include "VRManager.h"
 #include "VRThread.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsIScreenManager.h"
@@ -167,16 +171,26 @@ VRDisplayExternal::SubmitFrame(MacIOSurf
   if (ioSurface == nullptr) {
     NS_WARNING("VRDisplayExternal::SubmitFrame() could not get an IOSurface");
   } else {
     // FINDME!  Implement this
   }
   return result;
 }
 
+#elif defined(MOZ_WIDGET_ANDROID)
+
+bool
+VRDisplayExternal::SubmitFrame(const layers::SurfaceTextureDescriptor& aSurface,
+                               const gfx::Rect& aLeftEyeRect,
+                               const gfx::Rect& aRightEyeRect) {
+
+  return false;
+}
+
 #endif
 
 VRControllerExternal::VRControllerExternal(dom::GamepadHand aHand, uint32_t aDisplayID,
                                        uint32_t aNumButtons, uint32_t aNumTriggers,
                                        uint32_t aNumAxes, const nsCString& aId)
   : VRControllerHost(VRDeviceType::External, aHand, aDisplayID)
 {
   MOZ_COUNT_CTOR_INHERITED(VRControllerExternal, VRControllerHost);
@@ -196,33 +210,39 @@ VRControllerExternal::~VRControllerExter
 
 VRSystemManagerExternal::VRSystemManagerExternal()
  : mExternalShmem(nullptr)
 {
 #if defined(XP_MACOSX)
   mShmemFD = 0;
 #elif defined(XP_WIN)
   mShmemFile = NULL;
+#elif defined(MOZ_WIDGET_ANDROID)
+  mDoShutdown = false;
+  mExternalStructFailed = false;
 #endif
 }
 
 VRSystemManagerExternal::~VRSystemManagerExternal()
 {
   CloseShmem();
 }
 
 void
 VRSystemManagerExternal::OpenShmem()
 {
   if (mExternalShmem) {
     return;
+#if defined(MOZ_WIDGET_ANDROID)
+  } else if (mExternalStructFailed) {
+    return;
+#endif // defined(MOZ_WIDGET_ANDROID)
   }
 
 #if defined(XP_MACOSX)
-
   if (mShmemFD == 0) {
     mShmemFD = shm_open(kShmemName, O_RDWR, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
   }
   if (mShmemFD <= 0) {
     mShmemFD = 0;
     return;
   }
 
@@ -239,17 +259,16 @@ VRSystemManagerExternal::OpenShmem()
   if (mExternalShmem == MAP_FAILED) {
     // TODO - Implement logging
     mExternalShmem = NULL;
     CloseShmem();
     return;
   }
 
 #elif defined(XP_WIN)
-
   if (mShmemFile == NULL) {
     mShmemFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, kShmemName);
     if (mShmemFile == NULL) {
       // TODO - Implement logging
       CloseShmem();
       return;
     }
   }
@@ -261,53 +280,74 @@ VRSystemManagerExternal::OpenShmem()
     0,
     length.QuadPart);
 
   if (mExternalShmem == NULL) {
     // TODO - Implement logging
     CloseShmem();
     return;
   }
+#elif defined(MOZ_WIDGET_ANDROID)
+  mExternalShmem = (VRExternalShmem*)mozilla::GeckoVRManager::GetExternalContext();
+  if (!mExternalShmem) {
+    return;
+  }
+  if (mExternalShmem->version != kVRExternalVersion) {
+    mExternalShmem = nullptr;
+    mExternalStructFailed = true;
+    return;
+  }
+  if (mExternalShmem->size != sizeof(VRExternalShmem)) {
+    mExternalShmem = nullptr;
+    mExternalStructFailed = true;
+    return;
+  }
 #endif
   CheckForShutdown();
 }
 
 void
 VRSystemManagerExternal::CheckForShutdown()
 {
+#if defined(MOZ_WIDGET_ANDROID)
+  if (mDoShutdown) {
+    Shutdown();
+  }
+#else
   if (mExternalShmem) {
     if (mExternalShmem->generationA == -1 && mExternalShmem->generationB == -1) {
       Shutdown();
     }
   }
+#endif // defined(MOZ_WIDGET_ANDROID)
 }
 
 void
 VRSystemManagerExternal::CloseShmem()
 {
 #if defined(XP_MACOSX)
-  
   if (mExternalShmem) {
     munmap((void *)mExternalShmem, sizeof(VRExternalShmem));
     mExternalShmem = NULL;
   }
   if (mShmemFD) {
     close(mShmemFD);
   }
   mShmemFD = 0;
-  
 #elif defined(XP_WIN)
   if (mExternalShmem) {
     UnmapViewOfFile((void *)mExternalShmem);
     mExternalShmem = NULL;
   }
   if (mShmemFile) {
     CloseHandle(mShmemFile);
     mShmemFile = NULL;
   }
+#elif defined(MOZ_WIDGET_ANDROID)
+  mExternalShmem = NULL;
 #endif
 }
 
 /*static*/ already_AddRefed<VRSystemManagerExternal>
 VRSystemManagerExternal::Create()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -328,16 +368,19 @@ VRSystemManagerExternal::Destroy()
 void
 VRSystemManagerExternal::Shutdown()
 {
   if (mDisplay) {
     mDisplay = nullptr;
   }
   RemoveControllers();
   CloseShmem();
+#if defined(MOZ_WIDGET_ANDROID)
+  mDoShutdown = false;
+#endif
 }
 
 void
 VRSystemManagerExternal::NotifyVSync()
 {
   VRSystemManager::NotifyVSync();
 
   CheckForShutdown();
@@ -445,19 +488,29 @@ VRSystemManagerExternal::RemoveControlle
   mControllerCount = 0;
 }
 
 void
 VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState /* = nullptr */)
 {
   MOZ_ASSERT(mExternalShmem);
   if (mExternalShmem) {
-    // TODO - Add locking here for non-x86 platforms
+#if defined(MOZ_WIDGET_ANDROID)
+    if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->systemMutex)) == 0) {
+        memcpy(aDisplayState, (void*)&(mExternalShmem->state.displayState), sizeof(VRDisplayState));
+        if (aSensorState) {
+          memcpy(aSensorState, (void*)&(mExternalShmem->state.sensorState), sizeof(VRHMDSensorState));
+        }
+        pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->systemMutex));
+        mDoShutdown = aDisplayState->shutdown;
+    }
+#else
     VRExternalShmem tmp;
     memcpy(&tmp, (void *)mExternalShmem, sizeof(VRExternalShmem));
     if (tmp.generationA == tmp.generationB && tmp.generationA != 0 && tmp.generationA != -1) {
       memcpy(aDisplayState, &tmp.state.displayState, sizeof(VRDisplayState));
       if (aSensorState) {
         memcpy(aSensorState, &tmp.state.sensorState, sizeof(VRHMDSensorState));
       }
     }
+#endif // defined(MOZ_WIDGET_ANDROID)
   }
 }
--- a/gfx/vr/gfxVRExternal.h
+++ b/gfx/vr/gfxVRExternal.h
@@ -41,16 +41,20 @@ protected:
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
 #elif defined(XP_MACOSX)
   virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
+#elif defined(MOZ_WIDGET_ANDROID)
+  bool SubmitFrame(const layers::SurfaceTextureDescriptor& aSurface,
+                           const gfx::Rect& aLeftEyeRect,
+                           const gfx::Rect& aRightEyeRect) override;
 #endif
 
 public:
   explicit VRDisplayExternal(const VRDisplayState& aDisplayState);
   void Refresh();
 protected:
   virtual ~VRDisplayExternal();
   void Destroy();
@@ -101,22 +105,25 @@ public:
 protected:
   VRSystemManagerExternal();
   virtual ~VRSystemManagerExternal();
 
 private:
   // there can only be one
   RefPtr<impl::VRDisplayExternal> mDisplay;
   nsTArray<RefPtr<impl::VRControllerExternal>> mExternalController;
-
 #if defined(XP_MACOSX)
   int mShmemFD;
 #elif defined(XP_WIN)
   HANDLE mShmemFile;
+#elif defined(MOZ_WIDGET_ANDROID)
+  bool mDoShutdown;
+  bool mExternalStructFailed;
 #endif
+
   volatile VRExternalShmem* mExternalShmem;
 
   void OpenShmem();
   void CloseShmem();
   void CheckForShutdown();
 };
 
 } // namespace gfx
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -360,28 +360,16 @@ VRDisplayOSVR::SubmitFrame(MacIOSurface*
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect)
 {
   // XXX Add code to submit frame
   MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
   return false;
 }
 
-#elif defined(MOZ_ANDROID_GOOGLE_VR)
-
-bool
-VRDisplayOSVR::SubmitFrame(const mozilla::layers::EGLImageDescriptor*,
-                           const gfx::Rect& aLeftEyeRect,
-                           const gfx::Rect& aRightEyeRect)
-{
-  // XXX Add code to submit frame
-  MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
-  return false;
-}
-
 #endif
 
 void
 VRDisplayOSVR::StartPresentation()
 {
   // XXX Add code to start VR Presentation
 }
 
--- a/gfx/vr/gfxVROSVR.h
+++ b/gfx/vr/gfxVROSVR.h
@@ -41,20 +41,16 @@ protected:
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
 #elif defined(XP_MACOSX)
   virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
-#elif defined(MOZ_ANDROID_GOOGLE_VR)
-  virtual bool SubmitFrame(const mozilla::layers::EGLImageDescriptor*,
-                           const gfx::Rect& aLeftEyeRect,
-                           const gfx::Rect& aRightEyeRect) override;
 #endif
 
 public:
   explicit VRDisplayOSVR(OSVR_ClientContext* context,
                          OSVR_ClientInterface* iface,
                          OSVR_DisplayConfig* display);
 
 protected:
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -553,22 +553,22 @@ VRDisplayPuppet::SubmitFrame(MacIOSurfac
       MOZ_ASSERT(false, "No support for showing VR frames on MacOSX yet.");
       break;
     }
   }
 
   return false;
 }
 
-#elif defined(MOZ_ANDROID_GOOGLE_VR)
+#elif defined(MOZ_WIDGET_ANDROID)
 
 bool
-VRDisplayPuppet::SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor,
-                           const gfx::Rect& aLeftEyeRect,
-                           const gfx::Rect& aRightEyeRect)
+VRDisplayPuppet::SubmitFrame(const mozilla::layers::SurfaceTextureDescriptor& aDescriptor,
+                             const gfx::Rect& aLeftEyeRect,
+                             const gfx::Rect& aRightEyeRect)
 {
   MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
   return false;
 }
 
 #endif
 
 void
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -37,18 +37,18 @@ protected:
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
 #elif defined(XP_MACOSX)
   virtual bool SubmitFrame(MacIOSurface* aMacIOSurface,
                            const IntSize& aSize,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
-#elif defined(MOZ_ANDROID_GOOGLE_VR)
-  virtual bool SubmitFrame(const mozilla::layers::EGLImageDescriptor* aDescriptor,
+#elif defined(MOZ_WIDGET_ANDROID)
+  virtual bool SubmitFrame(const mozilla::layers::SurfaceTextureDescriptor& aDescriptor,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
 #endif
 
 public:
   explicit VRDisplayPuppet();
   void Refresh();
 
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -15,16 +15,18 @@
 #include "mozilla/dom/VREventObserver.h"
 #include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
 #include "mozilla/dom/ContentChild.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/GamepadManager.h"
 #include "mozilla/dom/VRServiceTest.h"
 #include "mozilla/layers/SyncObject.h"
 
+using namespace mozilla::dom;
+
 namespace {
 const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
   nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
 } // namespace
 
 namespace mozilla {
 namespace gfx {
 
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -99,31 +99,29 @@ struct ParamTraits<mozilla::gfx::VRDispl
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mType);
     WriteParam(aMsg, aParam.mDisplayID);
     WriteParam(aMsg, aParam.mPresentingGroups);
     WriteParam(aMsg, aParam.mGroupMask);
     WriteParam(aMsg, aParam.mFrameId);
-    WriteParam(aMsg, aParam.mPresentingGeneration);
     WriteParam(aMsg, aParam.mDisplayState);
     for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) {
       WriteParam(aMsg, aParam.mLastSensorState[i]);
     }
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDisplayID)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPresentingGroups)) ||
         !ReadParam(aMsg, aIter, &(aResult->mGroupMask)) ||
         !ReadParam(aMsg, aIter, &(aResult->mFrameId)) ||
-        !ReadParam(aMsg, aIter, &(aResult->mPresentingGeneration)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDisplayState))) {
       return false;
     }
     for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) {
       if (!ReadParam(aMsg, aIter, &(aResult->mLastSensorState[i]))) {
         return false;
       }
     }
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -20,27 +20,31 @@ EXPORTS += [
 LOCAL_INCLUDES += [
     '/dom/base',
     '/gfx/layers/d3d11',
     '/gfx/thebes',
 ]
 
 UNIFIED_SOURCES += [
     'gfxVR.cpp',
-    'gfxVROSVR.cpp',
     'ipc/VRLayerChild.cpp',
     'ipc/VRLayerParent.cpp',
     'ipc/VRManagerChild.cpp',
     'ipc/VRManagerParent.cpp',
     'VRDisplayClient.cpp',
     'VRDisplayPresentation.cpp',
     'VRManager.cpp',
     'VRThread.cpp',
 ]
 
+if CONFIG['OS_TARGET'] != 'Android':
+    UNIFIED_SOURCES += [
+        'gfxVROSVR.cpp',
+    ]
+
 # VRDisplayHost includes MacIOSurface.h which includes Mac headers
 # which define Size and Points types in the root namespace that
 # often conflict with our own types.
 SOURCES += [
     'gfxVRExternal.cpp',
     'gfxVRPuppet.cpp',
     'VRDisplayHost.cpp',
 ]
@@ -54,22 +58,17 @@ if CONFIG['OS_TARGET'] in ('WINNT', 'Lin
         'gfxVROpenVR.cpp',
     ]
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     SOURCES += [
         'gfxVROculus.cpp',
     ]
 
-if CONFIG['MOZ_ANDROID_GOOGLE_VR']:
-    SOURCES += [
-        'gfxVRGVR.cpp',
-        'jni/gfxGVRJNI.cpp',
-    ]
-    CXXFLAGS += ['-I%s' % CONFIG['MOZ_ANDROID_GOOGLE_VR_INCLUDE']]
+if CONFIG['OS_TARGET'] == 'Android':
     LOCAL_INCLUDES += ['/widget/android']
 
 IPDL_SOURCES = [
     'ipc/PVRLayer.ipdl',
     'ipc/PVRManager.ipdl',
 ]
 
 # For building with the real SDK instead of our local hack
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoVRManager.java
@@ -5,121 +5,20 @@
  * 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();
+    private static long mExternalContext;
 
     @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();
+    public static synchronized long getExternalContext() {
+      return mExternalContext;
     }
 
-    @WrapForJNI
-    /* package */ static void enableVRMode() {
-        if (!ThreadUtils.isOnUiThread()) {
-            ThreadUtils.postToUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    enableVRMode();
-                }
-            });
-            return;
-        }
-
-        if (mGVRDelegate == null) {
-            return;
-        }
-
-        mGVRDelegate.enableVRMode();
+    public static synchronized void setExternalContext(final long aExternalContext) {
+        mExternalContext = aExternalContext;
     }
 
-    @WrapForJNI
-    /* package */ static void disableVRMode() {
-        if (!ThreadUtils.isOnUiThread()) {
-            ThreadUtils.postToUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    disableVRMode();
-                }
-            });
-            return;
-        }
-
-        if (mGVRDelegate == null) {
-            return;
-        }
-
-        mGVRDelegate.disableVRMode();
-    }
 }
--- a/widget/android/GeckoVRManager.h
+++ b/widget/android/GeckoVRManager.h
@@ -4,79 +4,21 @@
  * 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* GetExternalContext() {
+    return (void*)mozilla::java::GeckoVRManager::GetExternalContext();
   }
-
-  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/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -420,17 +420,16 @@ 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()) {
             BrowserLocaleManagerSupport::Init();
             mozilla::ANRReporter::Init();
             mozilla::MemoryMonitor::Init();
             mozilla::widget::Telemetry::Init();
             mozilla::ThumbnailHelper::Init();