From bc5c08f979b968b287aab29db61d54437ba6952b Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Fri, 15 May 2020 18:10:27 +0200 Subject: [PATCH] Prevent deadlock when exiting WebXR/WebVR --- .../org/mozilla/vrbrowser/VRBrowserActivity.java | 5 ++++- app/src/main/cpp/ExternalVR.cpp | 12 ++++++++++-- app/src/main/cpp/VRBrowser.cpp | 10 +++++++--- app/src/main/cpp/VRBrowser.h | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 0602dbf6a..402478c56 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -1048,7 +1048,7 @@ void onEnterWebXR() { @Keep @SuppressWarnings("unused") - void onExitWebXR() { + void onExitWebXR(long aCallback) { if (Thread.currentThread() == mUiThread) { return; } @@ -1070,6 +1070,9 @@ void onExitWebXR() { if (!mWindows.isPaused()) { Log.d(LOGTAG, "Compositor resume begin"); mWindows.resumeCompositor(); + if (aCallback != 0) { + queueRunnable(() -> runCallbackNative(aCallback)); + } Log.d(LOGTAG, "Compositor resume end"); } }, 20); diff --git a/app/src/main/cpp/ExternalVR.cpp b/app/src/main/cpp/ExternalVR.cpp index a72f7e2d0..fea720f0c 100644 --- a/app/src/main/cpp/ExternalVR.cpp +++ b/app/src/main/cpp/ExternalVR.cpp @@ -378,9 +378,17 @@ ExternalVR::SetCompositorEnabled(bool aEnabled) { } m.compositorEnabled = aEnabled; if (aEnabled) { - VRBrowser::OnExitWebXR(); + // Set suppressFrames to avoid a deadlock between the sync surfaceChanged call + // and the gecko VRManager SubmitFrame result wait. + m.system.displayState.suppressFrames = true; + PushSystemState(); + VRBrowser::OnExitWebXR([=]{ + m.system.displayState.suppressFrames = false; + PushSystemState(); + }); } else { - // Set suppressFrames to avoid a deadlock between the compositor sync pause call and the gfxVRExternal SubmitFrame result wait. + // Set suppressFrames to avoid a deadlock between the compositor sync pause call + // and the gecko VRManager SubmitFrame result wait. m.system.displayState.suppressFrames = true; m.system.displayState.lastSubmittedFrameId = 0; m.lastFrameId = 0; diff --git a/app/src/main/cpp/VRBrowser.cpp b/app/src/main/cpp/VRBrowser.cpp index 12a788537..2c0afac07 100644 --- a/app/src/main/cpp/VRBrowser.cpp +++ b/app/src/main/cpp/VRBrowser.cpp @@ -33,7 +33,7 @@ const char* const kRegisterExternalContextSignature = "(J)V"; const char* const kOnEnterWebXRName = "onEnterWebXR"; const char* const kOnEnterWebXRSignature = "()V"; const char* const kOnExitWebXRName = "onExitWebXR"; -const char* const kOnExitWebXRSignature = "()V"; +const char* const kOnExitWebXRSignature = "(J)V"; const char* const kOnDismissWebXRInterstitialName = "onDismissWebXRInterstitial"; const char* const kOnDismissWebXRInterstitialSignature = "()V"; const char* const kOnWebXRRenderStateChangeName = "onWebXRRenderStateChange"; @@ -263,9 +263,13 @@ VRBrowser::OnEnterWebXR() { } void -VRBrowser::OnExitWebXR() { +VRBrowser::OnExitWebXR(const std::function& aCallback) { if (!ValidateMethodID(sEnv, sActivity, sOnExitWebXR, __FUNCTION__)) { return; } - sEnv->CallVoidMethod(sActivity, sOnExitWebXR); + jlong callback = 0; + if (aCallback) { + callback = reinterpret_cast(new std::function(aCallback)); + } + sEnv->CallVoidMethod(sActivity, sOnExitWebXR, callback); CheckJNIException(sEnv, __FUNCTION__); } diff --git a/app/src/main/cpp/VRBrowser.h b/app/src/main/cpp/VRBrowser.h index 07efb8af9..68fbac254 100644 --- a/app/src/main/cpp/VRBrowser.h +++ b/app/src/main/cpp/VRBrowser.h @@ -29,7 +29,7 @@ void HandleMoveEnd(jint aWidgetHandle, jfloat aX, jfloat aY, jfloat aZ, jfloat a void HandleBack(); void RegisterExternalContext(jlong aContext); void OnEnterWebXR(); -void OnExitWebXR(); +void OnExitWebXR(const std::function& aCallback); void OnDismissWebXRInterstitial(); void OnWebXRRenderStateChange(const bool aRendering); void RenderPointerLayer(jobject aSurface, const std::function& aFirstCompositeCallback);