diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-07-04 01:03:35 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-04 01:03:35 -0400 |
commit | b32bff3b9737ac6b6905cb85685a88dc31dc6739 (patch) | |
tree | 339ea3843451b1ada831d630bc2f7a0273119304 /support/hololens/OpenGLESPage.xaml.cpp | |
parent | e2441b27bb072b1c39a4f346074ade6c42bb27f2 (diff) | |
parent | 71abf1375de44fa9a599411f00ab0fdc64bfebf5 (diff) | |
download | servo-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.cpp | 154 |
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; + } +} |