aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ports/libsimpleservo/api/src/lib.rs3
-rw-r--r--support/hololens/ServoApp/BrowserPage.cpp91
-rw-r--r--support/hololens/ServoApp/BrowserPage.h16
3 files changed, 51 insertions, 59 deletions
diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs
index 02c80a2f402..f9fe314b8e5 100644
--- a/ports/libsimpleservo/api/src/lib.rs
+++ b/ports/libsimpleservo/api/src/lib.rs
@@ -488,7 +488,8 @@ impl ServoGlue {
.host_callbacks
.on_allow_navigation(url.to_string());
let window_event = WindowEvent::AllowNavigationResponse(pipeline_id, data);
- let _ = self.process_event(window_event);
+ self.events.push(window_event);
+ let _ = self.perform_updates();
}
},
EmbedderMsg::HistoryChanged(entries, current) => {
diff --git a/support/hololens/ServoApp/BrowserPage.cpp b/support/hololens/ServoApp/BrowserPage.cpp
index d6681375d11..afc07507d75 100644
--- a/support/hololens/ServoApp/BrowserPage.cpp
+++ b/support/hololens/ServoApp/BrowserPage.cpp
@@ -22,6 +22,8 @@ namespace winrt::ServoApp::implementation {
BrowserPage::BrowserPage() {
log("BrowserPage::BrowserPage()");
InitializeComponent();
+ InitializeConditionVariable(&mGLCondVar);
+ InitializeCriticalSection(&mGLLock);
Loaded(std::bind(&BrowserPage::OnPageLoaded, this, _1, _2));
Window::Current().CoreWindow().VisibilityChanged(
std::bind(&BrowserPage::OnVisibilityChanged, this, _1, _2));
@@ -31,15 +33,13 @@ void BrowserPage::Shutdown() {
log("BrowserPage::Shutdown()");
if (mServo != nullptr) {
- if (!IsLoopRunning()) {
+ if (!mLooping) {
// FIXME: this should not happen. In that case, we can't send the
// shutdown event to Servo.
} else {
- HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sShutdownEvent);
- RunOnGLThread([=] {mServo->RequestShutdown();});
- log("Waiting for Servo to shutdown");
- ::WaitForSingleObject(hEvent, INFINITE);
- StopRenderLoop();
+ RunOnGLThread([=] { mServo->RequestShutdown(); });
+ mLoopTask->wait();
+ mLoopTask.reset();
mServo.reset();
}
}
@@ -63,10 +63,10 @@ void BrowserPage::OnVisibilityChanged(CoreWindow const &,
// stopping the event loop, which we can't recover from yet (see comment in
// Loop())
- // if (visible && !IsLoopRunning()) {
+ // if (visible && !mLooping) {
// StartRenderLoop();
//}
- // if (!visible && IsLoopRunning()) {
+ // if (!visible && mLooping) {
// StopRenderLoop();
//}
}
@@ -92,15 +92,9 @@ void BrowserPage::RecoverFromLostDevice() {
/**** GL THREAD LOOP ****/
-bool BrowserPage::IsLoopRunning() {
- return mLoopTask != nullptr && !mLoopTask->is_done();
-}
-
-void BrowserPage::Loop(cancellation_token cancel) {
+void BrowserPage::Loop() {
log("BrowserPage::Loop(). GL thread: %i", GetCurrentThreadId());
- HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sWakeupEvent);
-
mOpenGLES.MakeCurrent(mRenderSurface);
EGLint panelWidth = 0;
@@ -118,51 +112,48 @@ void BrowserPage::Loop(cancellation_token cancel) {
throw winrt::hresult_error(E_FAIL, L"Recovering loop unimplemented");
}
- // mServo->SetBatchMode(true);
- // FIXME: ^ this should be necessary as we call perform_update
- // ourself. But enabling batch mode will make clicking a link
- // not working because during the click, this thread is not
- // waiting on the hEvent object. See the "wakeup" comment.
-
- log("Entering loop");
- while (!cancel.is_canceled()) {
- // Block until wakeup is called.
- // Or run full speed if animating (see OnAnimatingChanged),
- // it will endup blocking on Flush to limit rendering to 60FPS
- if (!mAnimating) {
- ::WaitForSingleObject(hEvent, INFINITE);
+ mServo->SetBatchMode(true);
+
+ while (true) {
+ EnterCriticalSection(&mGLLock);
+ while (mTasks.size() == 0 && !mAnimating && mLooping) {
+ SleepConditionVariableCS(&mGLCondVar, &mGLLock, INFINITE);
+ }
+ if (!mLooping) {
+ LeaveCriticalSection(&mGLLock);
+ break;
}
- mTasksMutex.lock();
for (auto &&task : mTasks) {
task();
}
mTasks.clear();
- mTasksMutex.unlock();
+ LeaveCriticalSection(&mGLLock);
mServo->PerformUpdates();
}
- log("Leaving loop");
mServo->DeInit();
cancel_current_task();
} // namespace winrt::ServoApp::implementation
void BrowserPage::StartRenderLoop() {
- if (IsLoopRunning()) {
+ if (mLooping) {
#if defined _DEBUG
throw winrt::hresult_error(E_FAIL, L"GL thread is already looping");
#else
return;
#endif
}
+ mLooping = true;
log("BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId());
- auto token = mLoopCancel.get_token();
- mLoopTask = std::make_unique<Concurrency::task<void>>(
- Concurrency::create_task([=] { Loop(token); }, token));
+ auto task = Concurrency::create_task([=] { Loop(); });
+ mLoopTask = std::make_unique<Concurrency::task<void>>(task);
}
void BrowserPage::StopRenderLoop() {
- if (IsLoopRunning()) {
- mLoopCancel.cancel();
- WakeUp();
+ if (mLooping) {
+ EnterCriticalSection(&mGLLock);
+ mLooping = false;
+ LeaveCriticalSection(&mGLLock);
+ WakeConditionVariable(&mGLCondVar);
mLoopTask->wait();
mLoopTask.reset();
}
@@ -192,9 +183,9 @@ void BrowserPage::OnHistoryChanged(bool back, bool forward) {
}
void BrowserPage::OnShutdownComplete() {
- log("Servo notified ShutdownComplete");
- HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sShutdownEvent);
- ::SetEvent(hEvent);
+ EnterCriticalSection(&mGLLock);
+ mLooping = false;
+ LeaveCriticalSection(&mGLLock);
}
void BrowserPage::OnAlert(std::wstring message) {
@@ -225,15 +216,17 @@ void BrowserPage::Flush() {
void BrowserPage::MakeCurrent() { mOpenGLES.MakeCurrent(mRenderSurface); }
void BrowserPage::WakeUp() {
- // FIXME: this won't work if it's triggered while the thread is not
- // waiting. We need a better looping logic.
- HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sWakeupEvent);
- ::SetEvent(hEvent);
+ RunOnGLThread([=] { });
}
bool BrowserPage::OnAllowNavigation(std::wstring) { return true; }
-void BrowserPage::OnAnimatingChanged(bool animating) { mAnimating = animating; }
+void BrowserPage::OnAnimatingChanged(bool animating) {
+ EnterCriticalSection(&mGLLock);
+ mAnimating = animating;
+ LeaveCriticalSection(&mGLLock);
+ WakeConditionVariable(&mGLCondVar);
+}
template <typename Callable> void BrowserPage::RunOnUIThread(Callable cb) {
swapChainPanel().Dispatcher().RunAsync(
@@ -300,10 +293,10 @@ void BrowserPage::OnSurfaceClicked(IInspectable const &,
}
void BrowserPage::RunOnGLThread(std::function<void()> task) {
- mTasksMutex.lock();
+ EnterCriticalSection(&mGLLock);
mTasks.push_back(task);
- mTasksMutex.unlock();
- WakeUp();
+ LeaveCriticalSection(&mGLLock);
+ WakeConditionVariable(&mGLCondVar);
}
} // namespace winrt::ServoApp::implementation
diff --git a/support/hololens/ServoApp/BrowserPage.h b/support/hololens/ServoApp/BrowserPage.h
index ac8f017422a..982b082579b 100644
--- a/support/hololens/ServoApp/BrowserPage.h
+++ b/support/hololens/ServoApp/BrowserPage.h
@@ -11,9 +11,6 @@
namespace winrt::ServoApp::implementation {
-static char sWakeupEvent[] = "SIGNAL_WAKEUP";
-static char sShutdownEvent[] = "SIGNAL_SHUTDOWN";
-
struct BrowserPage : BrowserPageT<BrowserPage>,
public servo::ServoDelegate {
public:
@@ -66,21 +63,22 @@ private:
void StartRenderLoop();
void StopRenderLoop();
- void Loop(Concurrency::cancellation_token);
- bool IsLoopRunning();
+ void Loop();
- Concurrency::cancellation_token_source mLoopCancel;
std::unique_ptr<Concurrency::task<void>> mLoopTask;
winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource;
EGLSurface mRenderSurface{EGL_NO_SURFACE};
std::unique_ptr<servo::Servo> mServo;
std::vector<std::function<void()>> mTasks;
- std::mutex mTasksMutex;
- OpenGLES mOpenGLES; // FIXME: shared pointer
+ CRITICAL_SECTION mGLLock;
+ CONDITION_VARIABLE mGLCondVar;
- bool mAnimating;
+ bool mAnimating = false;
+ bool mLooping = false;
+
+ OpenGLES mOpenGLES; // FIXME: shared pointer
};
} // namespace winrt::ServoApp::implementation