Skip to content

Commit

Permalink
Correct ExternaVR shutdown. Fixes #538 (#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
MortimerGoro authored and bluemarvin committed Sep 28, 2018
1 parent 164b1b5 commit 2b8f04b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 25 deletions.
31 changes: 23 additions & 8 deletions app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java
Expand Up @@ -179,12 +179,9 @@ protected void onStop() {
@Override
protected void onPause() {
if (mIsPresentingImmersive) {
queueRunnable(new Runnable() {
@Override
public void run() {
exitImmersiveNative();
}
});
// This needs to be sync to ensure that WebVR is correctly paused.
// Also prevents a deadlock in onDestroy when the BrowserWidget is released.
exitImmersiveSync();
}
mAudioEngine.pauseEngine();
SessionStore.get().setActive(false);
Expand Down Expand Up @@ -216,8 +213,6 @@ protected void onDestroy() {

SessionStore.get().clearListeners();
super.onDestroy();
// FIXME: HACK TO KILL GECKO BETWEEN RUNS.
android.os.Process.killProcess(android.os.Process.myPid());
}

@Override
Expand Down Expand Up @@ -276,6 +271,26 @@ public void run() {
}
}

private void exitImmersiveSync() {
Runnable exitImmersive = new Runnable() {
@Override
public void run() {
exitImmersiveNative();
synchronized(this) {
this.notifyAll();
}
}
};
synchronized (exitImmersive) {
queueRunnable(exitImmersive);
try {
exitImmersive.wait();
} catch (InterruptedException e) {
Log.e(LOGTAG, "Waiting for exit immersive onPause interrupted");
}
}
}

@Keep
@SuppressWarnings("unused")
void dispatchCreateWidget(final int aHandle, final SurfaceTexture aTexture, final int aWidth, final int aHeight) {
Expand Down
40 changes: 27 additions & 13 deletions app/src/main/cpp/ExternalVR.cpp
Expand Up @@ -6,7 +6,6 @@
#include "ExternalVR.h"
#include "VRBrowser.h"

#include "vrb/ConcreteClass.h"
#include "vrb/Matrix.h"
#include "vrb/Quaternion.h"
#include "vrb/Vector.h"
Expand Down Expand Up @@ -121,6 +120,7 @@ class Wait {
namespace crow {

struct ExternalVR::State {
static ExternalVR::State * sState;
mozilla::gfx::VRExternalShmem data;
mozilla::gfx::VRSystemState system;
mozilla::gfx::VRBrowserState browser;
Expand All @@ -132,16 +132,25 @@ struct ExternalVR::State {
bool waitingForExit;

State() : deviceCapabilities(0) {
memset(&data, 0, sizeof(mozilla::gfx::VRExternalShmem));
memset(&system, 0, sizeof(mozilla::gfx::VRSystemState));
memset(&browser, 0, sizeof(mozilla::gfx::VRBrowserState));
data.version = mozilla::gfx::kVRExternalVersion;
data.size = sizeof(mozilla::gfx::VRExternalShmem);
pthread_mutex_init(&data.systemMutex, nullptr);
pthread_mutex_init(&data.browserMutex, nullptr);
pthread_cond_init(&data.systemCond, nullptr);
pthread_cond_init(&data.browserCond, nullptr);
}

~State() {
pthread_mutex_destroy(&(data.systemMutex));
pthread_mutex_destroy(&(data.browserMutex));
pthread_cond_destroy(&(data.systemCond));
pthread_cond_destroy(&(data.browserCond));
}

void Reset() {
memset(&data, 0, sizeof(mozilla::gfx::VRExternalShmem));
memset(&system, 0, sizeof(mozilla::gfx::VRSystemState));
memset(&browser, 0, sizeof(mozilla::gfx::VRBrowserState));
data.version = mozilla::gfx::kVRExternalVersion;
data.size = sizeof(mozilla::gfx::VRExternalShmem);
system.displayState.mIsConnected = true;
system.displayState.mIsMounted = true;
const vrb::Matrix identity = vrb::Matrix::Identity();
Expand All @@ -153,11 +162,12 @@ struct ExternalVR::State {
waitingForExit = false;
}

~State() {
pthread_mutex_destroy(&(data.systemMutex));
pthread_mutex_destroy(&(data.browserMutex));
pthread_cond_destroy(&(data.systemCond));
pthread_cond_destroy(&(data.browserCond));
static ExternalVR::State& Instance() {
if (!sState) {
sState = new State();
}

return *sState;
}

void PullBrowserStateWhileLocked() {
Expand All @@ -179,9 +189,12 @@ struct ExternalVR::State {
}
};

ExternalVR::State * ExternalVR::State::sState = nullptr;

ExternalVRPtr
ExternalVR::Create() {
return std::make_shared<vrb::ConcreteClass<ExternalVR, ExternalVR::State> >();
ExternalVRPtr result(new ExternalVR());
return result;
}

mozilla::gfx::VRExternalShmem*
Expand Down Expand Up @@ -420,7 +433,8 @@ ExternalVR::StopPresenting() {
m.waitingForExit = true;
}

ExternalVR::ExternalVR(State& aState) : m(aState) {
ExternalVR::ExternalVR(): m(State::Instance()) {
m.Reset();
PushSystemState();
}

Expand Down
7 changes: 3 additions & 4 deletions app/src/main/cpp/ExternalVR.h
Expand Up @@ -40,6 +40,7 @@ class ExternalVR : public ImmersiveDisplay {
const double aBottomDegrees) override;
void SetEyeOffset(const device::Eye aEye, const float aX, const float aY, const float aZ) override;
void SetEyeResolution(const int32_t aX, const int32_t aY) override;
void CompleteEnumeration() override;
// ExternalVR interface
void PushSystemState();
void PullBrowserState();
Expand All @@ -50,14 +51,12 @@ class ExternalVR : public ImmersiveDisplay {
bool WaitFrameResult();
void GetFrameResult(int32_t& aSurfaceHandle, device::EyeRect& aLeftEye, device::EyeRect& aRightEye) const;
void StopPresenting();
void CompleteEnumeration() override;
~ExternalVR();
protected:
struct State;
ExternalVR(State& aState);
~ExternalVR();
ExternalVR();
private:
State& m;
ExternalVR() = delete;
VRB_NO_DEFAULTS(ExternalVR)
};

Expand Down

0 comments on commit 2b8f04b

Please sign in to comment.