aboutsummaryrefslogtreecommitdiffstats
path: root/support/hololens/OpenGLESPage.xaml.cpp
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-07-04 01:03:35 -0400
committerGitHub <noreply@github.com>2019-07-04 01:03:35 -0400
commitb32bff3b9737ac6b6905cb85685a88dc31dc6739 (patch)
tree339ea3843451b1ada831d630bc2f7a0273119304 /support/hololens/OpenGLESPage.xaml.cpp
parente2441b27bb072b1c39a4f346074ade6c42bb27f2 (diff)
parent71abf1375de44fa9a599411f00ab0fdc64bfebf5 (diff)
downloadservo-b32bff3b9737ac6b6905cb85685a88dc31dc6739.tar.gz
servo-b32bff3b9737ac6b6905cb85685a88dc31dc6739.zip
Auto merge of #23696 - servo:hl, r=jdm
Add UWP port - bis This is #23658 with some fixes: - removed nspr from DLL dependencies (was breaking VS build) - exclude symbols from header file (was breaking VS build) - rebased Before merging: - please check the rebased commit that introduces the `--uwp` option (things moved around since https://github.com/servo/servo/commit/7c85dc09b59e653caf60cb18d3b3fdea2ba4d4ae) - should we wait until the WR fix lands upstream? <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23696) <!-- Reviewable:end -->
Diffstat (limited to 'support/hololens/OpenGLESPage.xaml.cpp')
-rw-r--r--support/hololens/OpenGLESPage.xaml.cpp154
1 files changed, 154 insertions, 0 deletions
diff --git a/support/hololens/OpenGLESPage.xaml.cpp b/support/hololens/OpenGLESPage.xaml.cpp
new file mode 100644
index 00000000000..c4c7dd21e3a
--- /dev/null
+++ b/support/hololens/OpenGLESPage.xaml.cpp
@@ -0,0 +1,154 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+#include "pch.h"
+#include "OpenGLESPage.xaml.h"
+#include "Servo.h"
+
+using namespace hlservo;
+using namespace Platform;
+using namespace Concurrency;
+using namespace Windows::Foundation;
+
+static char sWakeupEvent[] = "SIGNAL_WAKEUP";
+
+OpenGLESPage::OpenGLESPage()
+ : OpenGLESPage(nullptr)
+{
+}
+
+OpenGLESPage::OpenGLESPage(OpenGLES* openGLES)
+ : mOpenGLES(openGLES)
+ , mRenderSurface(EGL_NO_SURFACE)
+{
+ InitializeComponent();
+ Windows::UI::Core::CoreWindow ^ window = Windows::UI::Xaml::Window::Current->CoreWindow;
+ window->VisibilityChanged += ref new Windows::Foundation::TypedEventHandler<Windows::UI::Core::CoreWindow ^,
+ Windows::UI::Core::VisibilityChangedEventArgs ^>(this, &OpenGLESPage::OnVisibilityChanged);
+ this->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &OpenGLESPage::OnPageLoaded);
+}
+
+OpenGLESPage::~OpenGLESPage()
+{
+ StopRenderLoop();
+ DestroyRenderSurface();
+}
+
+void OpenGLESPage::OnPageLoaded(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e)
+{
+ CreateRenderSurface();
+ StartRenderLoop();
+}
+
+void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow ^ sender,
+ Windows::UI::Core::VisibilityChangedEventArgs ^ args)
+{
+ if (args->Visible && mRenderSurface != EGL_NO_SURFACE) {
+ StartRenderLoop();
+ } else {
+ StopRenderLoop();
+ }
+}
+
+void OpenGLESPage::CreateRenderSurface()
+{
+ if (mOpenGLES && mRenderSurface == EGL_NO_SURFACE) {
+ mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel);
+ }
+}
+
+void OpenGLESPage::DestroyRenderSurface()
+{
+ if (mOpenGLES) {
+ mOpenGLES->DestroySurface(mRenderSurface);
+ }
+ mRenderSurface = EGL_NO_SURFACE;
+}
+
+void OpenGLESPage::RecoverFromLostDevice()
+{
+ StopRenderLoop();
+ {
+ critical_section::scoped_lock lock(mRenderSurfaceCriticalSection);
+
+ DestroyRenderSurface();
+ mOpenGLES->Reset();
+ CreateRenderSurface();
+ }
+ StartRenderLoop();
+}
+
+void OpenGLESPage::StartRenderLoop()
+{
+ if (mRenderLoopWorker != nullptr && mRenderLoopWorker->Status == Windows::Foundation::AsyncStatus::Started) {
+ return;
+ }
+
+ auto loop = [this](Windows::Foundation::IAsyncAction ^ action) {
+ critical_section::scoped_lock lock(mRenderSurfaceCriticalSection);
+
+ HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sWakeupEvent);
+
+ // Called by Servo
+ Servo::sMakeCurrent = [this]() {
+ /* EGLint panelWidth = 0; */
+ /* EGLint panelHeight = 0; */
+ /* mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); */
+ /* glViewport(0, 0, panelWidth, panelHeight); */
+ /* mServo->SetSize(panelWidth, panelHeight); */
+ mOpenGLES->MakeCurrent(mRenderSurface);
+ };
+
+ // Called by Servo
+ Servo::sFlush = [this]() {
+ if (mOpenGLES->SwapBuffers(mRenderSurface) != GL_TRUE) {
+ // The call to eglSwapBuffers might not be successful (i.e. due to Device Lost)
+ // If the call fails, then we must reinitialize EGL and the GL resources.
+ swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High,
+ ref new Windows::UI::Core::DispatchedHandler([=]() {
+ RecoverFromLostDevice();
+ }, CallbackContext::Any));
+ }
+ };
+
+ mOpenGLES->MakeCurrent(mRenderSurface);
+
+ EGLint panelWidth = 0;
+ EGLint panelHeight = 0;
+ mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight);
+ glViewport(0, 0, panelWidth, panelHeight);
+ mServo = new Servo(panelWidth, panelHeight);
+
+ while (action->Status == Windows::Foundation::AsyncStatus::Started) {
+ // Block until Servo::sWakeUp is called.
+ // Or run full speed if animating (see on_animating_changed),
+ // it will endup blocking on SwapBuffers to limit rendering to 60FPS
+ if (!Servo::sAnimating) {
+ ::WaitForSingleObject(hEvent, INFINITE);
+ }
+ mServo->PerformUpdates();
+ }
+ };
+
+ auto workItemHandler = ref new Windows::System::Threading::WorkItemHandler(loop);
+
+ // Run Servo task in a high priority background thread.
+ mRenderLoopWorker = Windows::System::Threading::ThreadPool::RunAsync(
+ workItemHandler,
+ Windows::System::Threading::WorkItemPriority::High,
+ Windows::System::Threading::WorkItemOptions::TimeSliced);
+
+ Servo::sWakeUp = []() {
+ HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sWakeupEvent);
+ ::SetEvent(hEvent);
+ };
+}
+
+void OpenGLESPage::StopRenderLoop()
+{
+ if (mRenderLoopWorker) {
+ mRenderLoopWorker->Cancel();
+ mRenderLoopWorker = nullptr;
+ }
+}